//+-------------------------------------------------------------------+
//|                                               Nanningbob 10.2.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 "Up. "
#define  down "Down. "
#define  ranging "Ranging. "
#define  none "None. "
#define  both "Both. "
#define  buy "Buy"
#define  sell "Sell"

//Pending trade price line
#define  pendingpriceline "Pending price line"
//Hidden sl and tp lines. If UseStealth enabled, the bot will close trades on a touch/break of these lines.
//Each line is named with its appropriate prefix and the ticket number of the relevant trade
#define  TpPrefix "Tp"
#define  SlPrefix "Sl"

//Indi definitions
#define  buyonly "Buy Only. "
#define  sellonly "Sell Only. "
#define  buyhold "Buy and hold. "
#define  sellhold "Sell and hold. "
#define  rising   "Angle is rising. "
#define  falling   "Angle is falling. "
#define  unchanged   "Angle is unchanged."

#define  version "Version 1a"



/*

Matt Kennel has provided the code for bool O_R_CheckForHistory(int ticket). Cheers Matt, You are a star.


Code for adding debugging Sleep
Alert("G");
int x = 0;
while (x == 0) Sleep(100);

Code for returning a value as pips. The example returns the range of the previous candle
   int PipDivisor = 1;
   if (Digits == 3 || Digits == 5) PipDivisor = 10;
   double CandleRange = ((High[1] - Low[1]) / Point) / PipDivisor;

Standard order loop code
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderMagicNumber() != MagicNumber) continue;

   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)

Code from George, to detect the shift of an order open time
int shift = iBarShift(NULL,Period(),OrderOpenTime(), false);

FUNCTIONS LIST
void DisplayUserFeedback()
int init()
int start()

----Trading----

void LookForTradingOpportunities()
   double CalculateStopLoss(int type)
   double CalculateTakeProfit(int type)
   bool IsTradingAllowed()
   double CalculateLotSize(double price1, double price2)
bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take)
   void ModifyOrder(int ticket, double stop, double take)
void CountOpenTrades()
   void InsertStopLoss(int ticket)
   void InsertTakeProfit(int ticket)
bool CloseTrade(int ticket)
bool LookForTradeClosure(int ticket)
bool CheckTradingTimes()
void CloseAllTrades()
double CalculateTradeProfitInPips()
bool CloseEnough(double num1, double num2)
void GetVolatilityGroup{}

----Hidden sl/tp---- Doubles up for pending trades-based ea's
void DrawPendingPriceLines()
void DeletePendingPriceLines()
void ReplaceMissingSlTpLines()
void DeleteOrphanTpSlLines()

----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()
void CalculateDailyResult()
double GetSlope(int tf, int shift)
double GetWoh(int tf, int shift)
double GetMa(int tf, int period, int mashift, int method, int ap, int shift)

----Pivots and support/resistance----
void CalculatePivots()
void GetSupport(int tf)
void GetResistance(int tf)

----Trade management module----
void TradeManagementModule()
void BreakEvenStopLoss()
void JumpingStopLoss() 
void HiddenTakeProfit()
void HiddenStopLoss()
void TrailingStopLoss()
void CandlestickTrailingStop()
void ReportError()

*/

string  gen="----General inputs----";
double  Lot=0.01;
int     RiskPercent = 0;//Set to zero to disable and use Lot
bool    StopTrading=false;
bool    TradeLong=true;
bool    TradeShort=true;
int     TakeProfit=100;
int     StopLoss=100;
int     MagicNumber=0;
string  TradeComment="";
bool    CriminalIsECN=false;
double  MaxSpread=120;

extern string  ind="----10.2 Indicators----";
extern bool    EveryTickMode=false;//Tells the bot to read the indis at every tick
extern int     IndiReadTimeFrame=1;
string  slo="Slope";//No externs. Uses my adapted version of the indi that has no externs
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Slope
double         D1SlopeVal, ChartSlopeVal, PrevD1SlopeVal, PrevChartSlopeVal;
string         D1SlopeTrend, ChartSlopeTrend, D1SlopeAngle, ChartSlopeAngle;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Weekly open trend finding
extern string  wot="WeaklyOpenHistogram 2x1";
extern int     barsToProcess = 1000;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
double         D1WohVal, ChartWohVal, PrevD1WohVal, PrevChartWohVal;
string         D1WohTrend, ChartWohTrend, D1WohAngle, ChartWohAngle;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Weekly direction
string         WeeklyDirection;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Pivots and s/r
double         MonthlyPivot, WeeklyPivot;
double         MMR1, MR1, MMR2, MR2, MMR3, MR3, MMS1, MS1, MMS2, MS2, MMS3, MS3;//MonthlyMidResistance1. MonthlyResistance1 etc
double         WR1, WR2, WR3, WS1, WS2, WS3;//WeeklyResistance1 etc
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
extern string  mai="----Moving averages----";
int     MaTF=0;//Time frame defaults to current chart 
extern int     MaPeriod=5;
extern string  mame="Method: 0=sma; 1=ema; 2=smma;  3=lwma";
extern int     MaMethod=3;
extern string  maap="Applied price: 0=Close; 1=Open; 2=High";
extern string  maap1="3=Low; 4=Median; 5=Typical; 6=Weighted";
extern int     MaAppliedPrice=1;
extern int     BlueMaShift=1;//The MA Shift input
extern int     GreenMaShift=3;//The MA Shift input
extern int     MaroonMaShift=5;//The MA Shift input
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
double         ChartBlueMaVal, ChartGreenMaVal, ChartMaroonMaVal, D1BlueMaVal, D1GreenMaVal, D1MaroonMaVal;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//Support and resistance
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
double         D1Support, D1Resistance, ChartSupport, ChartResistance;
string         D1SupportText, D1ResistanceText, ChartSupportText, ChartResistanceText;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//Hidden tp/sl inputs.
string  hts="----Stealth stop loss and take profit inputs----";
int     HiddenPips=0;//Added to the 'hard' sl and tp and used for closure calculations
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
double         HiddenStopLoss, HiddenTakeProfit;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

string  tt="----Trading hours----";
string  Trade_Hours= "Set Morning & Evening Hours";
string  Trade_Hoursi= "Use 24 hour, local time clock";
string  Trade_Hours_M= "Morning Hours 0-12";
int    start_hourm = 0;
int    end_hourm = 12;
string  Trade_Hours_E= "Evening Hours 12-24";
int    start_houre = 12;
int    end_houre = 24;

string  tmm="----Trade management module----";
//Breakeven has to be enabled for JS and TS to work.
string  BE="Break even settings";
bool    BreakEven=false;
int     BreakEvenPips=10;
int     BreakEvenProfit=5;
string  cts="----Candlestick trailing stop----";
bool    UseCandlestickTrailingStop=false;
int     CstTimeFrame=0;//Defaults to current chart
int     CstTrailCandles=1;//Defaults to previous candle
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int            OldCstBars;//For candlestick ts
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

string  JSL="Jumping stop loss settings";
bool    JumpingStop=false;
int     JumpingStopPips=10;
bool    AddBEP=true;
string  TSL="Trailing stop loss settings";
bool    TrailingStop=false;
int     TrailingStopPips=20;

extern string  vg="----Volatility groups----";
extern string  Group.1="NZDCAD, AUDUSD, EURCHF, EURGBP";
extern string  Group.2="AUDNZD, NZDUSD, CHFJPY, AUDCAD, USDCAD";
extern string  Group.3="NZDJPY, AUDCHF, AUDJPY, USDJPY, EURUSD, NZDCHF, CADCHF";
extern string  Group.4="GBPJPY, GBPCHF, CADJPY, EURCAD, EURAUD, USDCHF, GBPUSD, EURJPY";
extern string  Group.5="GBPNZD, EURNZD, GBPAUD, GBPCAD";
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int            VolatilityGroup;//Will be 1,2,3,4 or 5 depending on the group
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

extern string  mis="----Odds and ends----";
extern int     DisplayGapSize=30;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
string         Gap, ScreenMessage;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//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            RetryCount = 10;//Will make this number of attempts to get around the trade context busy error.


//Trading variables
int            TicketNo = -1, OpenTrades;
bool           CanTradeThisPair;//Will be false when this pair fails the currency can only trade twice filter, or the balanced trade filter
bool           BuyOpen, SellOpen, PendingBuyOpen, PendingSellOpen;//Might need further refinement to reflect the pending type
double         upl;//For keeping track of the upl of hedged positions





//Running total of trades
int            LossTrades, WinTrades;
double         OverallProfit;

//Misc
int            OldBars;
string         PipDescription=" pips";
bool           ForceTradeClosure;
int            TurnOff=0;//For turning off functions without removing their code



void DisplayUserFeedback()
{
   
   /*
   if (IsTesting() && !IsVisualMode()) return;

   ScreenMessage = "";
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Updates for this EA are to be found at http://www.stevehopwoodforex.com", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Feeling generous? Help keep the coder going with a small Paypal donation to pianodoodler@hotmail.com", NL);
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, TimeToStr(TimeLocal(), TIME_DATE|TIME_MINUTES|TIME_SECONDS), NL );
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, version, NL );
      
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);      
   if (TradeLong) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Taking long trades", NL);
   if (TradeShort) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Taking short trades", NL);
   if (!TradeLong && !TradeShort) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Both TradeLong and TradeShort are set to false", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Lot size: ", Lot, " (Criminal's minimum lot size: ", MarketInfo(Symbol(), MODE_MINLOT), ")", 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, "MaxSpread = ", MaxSpread, ": Spread = ", MarketInfo(Symbol(), MODE_SPREAD), NL);
   
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, 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

      
   //Running total of trades
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Results today. Wins: ", WinTrades, ": Losses ", LossTrades,
                                     ": P/L ", DoubleToStr(OverallProfit, 2), NL);
   
      
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);
   */
   
   string Indent = "        ";
   ScreenMessage = "";
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Updates for this EA are to be found at http://www.stevehopwoodforex.com", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Feeling generous? Help keep the coder going with a small Paypal donation to pianodoodler@hotmail.com", NL);
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, TimeToStr(TimeLocal(), TIME_DATE|TIME_MINUTES|TIME_SECONDS), NL );
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, version, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Volatility group: ", VolatilityGroup, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Slope indi", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, Indent, "D1 value ", D1SlopeVal, ": Trend is ", D1SlopeTrend, 
                                                                D1SlopeAngle, NL);                                                                
   if (Period() != PERIOD_D1) ScreenMessage = StringConcatenate(ScreenMessage,Gap, Indent, "Chart value ", ChartSlopeVal, 
                                                                                    ": Trend is ", ChartSlopeTrend, 
                                                                                   ChartSlopeAngle ,NL);

   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Woh 2x1 indi", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, Indent, "D1 value ", D1WohVal, ": Trend is ", D1WohTrend, D1WohAngle, NL);
   if (Period() != PERIOD_D1) ScreenMessage = StringConcatenate(ScreenMessage,Gap, Indent, "Chart value ", ChartWohVal, ": Trend is ", ChartWohTrend, ChartWohAngle, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Movement from start of week: ", WeeklyDirection, NL);

   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Pivots", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, Indent, "Monthly: ", MonthlyPivot, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, Indent, Indent, 
                                     "Mid R1 ", MMR1, ": R1 ", MR1,
                                     ": Mid R2 ", MMR2, ": R2 ", MR2,
                                     ": Mid R3 ", MMR3, ": R3 ", MR3, 
                                     NL, Gap, Indent, Indent,
                                     "Mid S1 ", MMS1, ": S1 ", MS1,
                                     ": Mid S2 ", MMS2, ": S2 ", MS2,
                                     ": Mid S3 ", MMS3, ": S3 ", MS3,   
                                     NL);
      
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, Indent, "Weekly: ", WeeklyPivot, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, Indent, Indent, 
                                     "R1 ", WR1,
                                     ": R2 ", WR2,
                                     ": R3 ", WR3, 
                                     NL, Gap, Indent, Indent,
                                     "S1 ", WS1,
                                     ": S2 ", WS2,
                                     ": S3 ", WS3,   
                                     NL);

   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Support/resistance", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, Indent, 
                                     "Daily: Resistance ", D1ResistanceText, " at ", D1Resistance,
                                     ": Support ", D1SupportText, " at ", D1Support,
                                     NL);
   
   if (Period() != PERIOD_D1)
   {
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, Indent, 
                                     "Chart: Resistance ", ChartResistanceText, " at ", ChartResistance,
                                     ": Support ", ChartSupportText, " at ", ChartSupport,
                                     NL);
   }//if (Period() != PERIOD_D1)

   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Moving Averages", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, Indent, "Daily",
                                     "Blue ", D1BlueMaVal,
                                     ": Green ", D1GreenMaVal,
                                     ": Maroon ", D1MaroonMaVal,
                                     NL);
   if (Period() != PERIOD_D1)
   {
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, Indent, "Chart",
                                     "Blue ", ChartBlueMaVal,
                                     ": Green ", ChartGreenMaVal,
                                     ": Maroon ", ChartMaroonMaVal,
                                     NL);
   }//if (Period() != PERIOD_D1)
   
   
   
   Comment(ScreenMessage);


}//void DisplayUserFeedback()


//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
//----

   //Adapt to x digit criminals
   int multiplier = 1;
   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;
   HiddenPips*= multiplier;
   
   BreakEvenPips*= multiplier;
   BreakEvenProfit*= multiplier;
   JumpingStopPips*= multiplier;
   TrailingStopPips*= multiplier;

   //Jumping/trailing stops need breakeven set before they work properly
   if ((JumpingStop || TrailingStop) && !BreakEven) 
   {
      BreakEven = true;
      if (JumpingStop) BreakEvenPips = JumpingStopPips;
      if (TrailingStop) BreakEvenPips = TrailingStopPips;
   }//if (JumpingStop || TrailingStop) 
   
   Gap="";
   if (DisplayGapSize >0)
   {
      for (int cc=0; cc< DisplayGapSize; cc++)
      {
         Gap = StringConcatenate(Gap, " ");
      }   
   }//if (DisplayGapSize >0)
   
   //Reset CriminIsECN if crim is IBFX and the punter does not know or, like me, keeps on forgetting
   string name = TerminalCompany();
   int ispart = StringFind(name, "IBFX", 0);
   if (ispart < 0) ispart = StringFind(name, "Interbank FX", 0);
   if (ispart > -1) CriminalIsECN = true;   
   
   //Calculate volatioity group the pair belongs to
   GetVolatilityGroup();
   
   if (TradeComment == "") TradeComment = " ";
   OldBars = Bars;
   TicketNo = -1;
   ReadIndicatorValues();//For initial display in case user has turned of constant re-display
   DisplayUserFeedback();
   //This forces the platform to 2048 bars of data - necessary if this is a new CrapT4 installation
   iBars(NULL, Period() );
   
   //Call sq's show trades indi
   //iCustom(NULL, 0, "SQ_showTrades",Magic, 0,0);

   
//----
   return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
//----
   Comment("");
//----
   return(0);
}

void GetVolatilityGroup()
{
   string symbol = StringSubstr(Symbol(), 0, 6);

   if (StringFind(Group.1, symbol) > -1)
   {
      VolatilityGroup = 1;
   }//if (StringFind(Group.1, symbol) > -1)
   
   if (StringFind(Group.2, symbol) > -1)
   {
      VolatilityGroup = 2;
   }//if (StringFind(Group.1, symbol) > -1)
   
   if (StringFind(Group.3, symbol) > -1)
   {
      VolatilityGroup = 3;
   }//if (StringFind(Group.1, symbol) > -1)
   
   if (StringFind(Group.4, symbol) > -1)
   {
      VolatilityGroup = 4;
   }//if (StringFind(Group.1, symbol) > -1)
   
   if (StringFind(Group.5, symbol) > -1)
   {
      VolatilityGroup = 5;
   }//if (StringFind(Group.1, symbol) > -1)
   

}//End void GetVolatilityGroup{}


bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take)
{
   //pah (Paul) contributed the code to get around the trade context busy error. Many thanks, Paul.
   
   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);

   //RetryCount is declared as 10 in the Trading variables section at the top of this file
   for (int cc = 0; cc < RetryCount; cc++)
   {
      for (int d = 0; (d < RetryCount) && IsTradeContextBusy(); d++) Sleep(100);

      RefreshRates();
      if (type == OP_BUY) price = NormalizeDouble(Ask, Digits);
      if (type == OP_SELL) price = NormalizeDouble(Bid, Digits);
      
      if (!CriminalIsECN) int ticket = OrderSend(Symbol(),type, lotsize, price, slippage, stop, take, comment, MagicNumber, expiry, col);
   
   
      //Is a 2 stage criminal
      if (CriminalIsECN)
      {
         ticket = OrderSend(Symbol(),type, lotsize, price, slippage, 0, 0, comment, MagicNumber, expiry, col);
         if (ticket > -1)
         {
	           ModifyOrder(ticket, stop, take);
         }//if (ticket > 0)}
      }//if (CriminalIsECN)
      
      if (ticket > -1) break;//Exit the trade send loop
      if (cc == RetryCount - 1) return(false);
   
      //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";
         int err=GetLastError();
         Alert(Symbol(), " ", WindowExpertName(), " ", stype," order send failed with error(",err,"): ",ErrorDescription(err));
         Print(Symbol(), " ", WindowExpertName(), " ", stype," order send failed with error(",err,"): ",ErrorDescription(err));
         return(false);
      }//if (ticket < 0)  
   }//for (int cc = 0; cc < RetryCount; cc++);
   
   
   TicketNo = ticket;
   //Make sure the trade has appeared in the platform's history to avoid duplicate trades.
   //My mod of Matt's code attempts to overcome the bastard crim's attempts to overcome Matt's code.
   bool TradeReturnedFromCriminal = false;
   while (!TradeReturnedFromCriminal)
   {
      TradeReturnedFromCriminal = O_R_CheckForHistory(ticket);
      if (!TradeReturnedFromCriminal)
      {
         Alert(Symbol(), " sent trade not in your trade history yet. Turn of this ea NOW.");
      }//if (!TradeReturnedFromCriminal)
   }//while (!TradeReturnedFromCriminal)
   
   //Got this far, so trade send succeeded
   return(true);
   
}//End bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take)

void ModifyOrder(int ticket, double stop, double take)
{
   //Modifies an order already sent if the crim is ECN.

   if (stop == 0 && take == 0) return; //nothing to do

   if (!OrderSelect(ticket, SELECT_BY_TICKET) ) return;//Trade does not exist, so no mod needed
   
   //RetryCount is declared as 10 in the Trading variables section at the top of this file   
   for (int cc = 0; cc < RetryCount; cc++)
   {
      for (int d = 0; (d < RetryCount) && IsTradeContextBusy(); d++) Sleep(100);
        if (take > 0 && stop > 0)
        {
           while(IsTradeContextBusy()) Sleep(100);
           if (OrderModify(ticket, OrderOpenPrice(), stop, take, OrderExpiration(), CLR_NONE)) return;           
        }//if (take > 0 && stop > 0)
   
        if (take != 0 && stop == 0)
        {
           while(IsTradeContextBusy()) Sleep(100);
           if (OrderModify(ticket, OrderOpenPrice(), OrderStopLoss(), take, OrderExpiration(), CLR_NONE)) return;
        }//if (take == 0 && stop != 0)

        if (take == 0 && stop != 0)
        {
           while(IsTradeContextBusy()) Sleep(100);
           if (OrderModify(ticket, OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE)) return;
        }//if (take == 0 && stop != 0)
   }//for (int cc = 0; cc < RetryCount; cc++)
   
   //Got this far, so the order modify failed
   int err=GetLastError();
   Print(Symbol(), " SL/TP  order modify failed with error(",err,"): ",ErrorDescription(err));               
   Alert(Symbol(), " SL/TP  order modify failed with error(",err,"): ",ErrorDescription(err));               

}//void ModifyOrder(int ticket, double tp, double sl)

//=============================================================================
//                           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 IsTradingAllowed()
{
   //Returns false if any of the filters should cancel trading, else returns true to allow trading
   
      
   //Maximum spread
   if (MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread) return(false);
 
 
   
   return(true);


}//End bool IsTradingAllowed()

double CalculateLotSize(double price1, double price2)
{
   //Calculate the lot size by risk. Code kindly supplied by jmw1970. Nice one jmw.
   
   if (price1 == 0 || price2 == 0) return(Lot);//Just in case
   
   double FreeMargin = AccountFreeMargin();
   double TickValue = MarketInfo(Symbol(),MODE_TICKVALUE) ;
   double LotStep = MarketInfo(Symbol(),MODE_LOTSTEP);


   double SLPts = MathAbs(price1 - price2);
   SLPts/= Point;
   
   double Exposure = SLPts * TickValue; // Exposure based on 1 full lot

   double AllowedExposure = (FreeMargin * RiskPercent) / 100;
   
   int TotalSteps = ((AllowedExposure / Exposure) / LotStep);
   double LotSize = TotalSteps * LotStep;

   double MinLots = MarketInfo(Symbol(), MODE_MINLOT);
   double MaxLots = MarketInfo(Symbol(), MODE_MAXLOT);
   
   if (LotSize < MinLots) LotSize = MinLots;
   if (LotSize > MaxLots) LotSize = MaxLots;
   return(LotSize);

}//double CalculateLotSize(double price1, double price1)

double CalculateStopLoss(int type)
{
   //Returns the stop loss for use in LookForTradingOpps and InsertMissingStopLoss
   double stop, price;

   RefreshRates();
   
   if (type == OP_BUY)
   {
      price = Ask;
      if (StopLoss > 0) 
      {
         stop = NormalizeDouble(price - (StopLoss * Point), Digits);
         HiddenStopLoss = stop;
      }//if (StopLoss > 0) 

      
      if (HiddenPips > 0 && stop > 0) stop = NormalizeDouble(stop - (HiddenPips * Point), Digits);
   }//if (type == OP_BUY)
   
   if (type == OP_SELL)
   {
      price = Bid;
      if (StopLoss > 0) 
      {
         stop = NormalizeDouble(price + (StopLoss * Point), Digits);
         HiddenStopLoss = stop;         
      }//if (StopLoss > 0) 
      
      if (HiddenPips > 0 && stop > 0) stop = NormalizeDouble(stop + (HiddenPips * Point), Digits);

   }//if (type == OP_SELL)
   
   return(stop);
   
}//End double CalculateStopLoss(int type)

double CalculateTakeProfit(int type)
{
   //Returns the stop loss for use in LookForTradingOpps and InsertMissingStopLoss
   double take, price;

   RefreshRates();
   
   if (type == OP_BUY)
   {
      price = Ask;
      if (TakeProfit > 0) 
      {
         take = NormalizeDouble(price + (TakeProfit * Point), Digits);
         HiddenTakeProfit = take;
      }//if (TakeProfit > 0) 

         
      if (HiddenPips > 0 && take > 0) take = NormalizeDouble(take + (HiddenPips * Point), Digits);

   }//if (type == OP_BUY)
   
   if (type == OP_SELL)
   {
      price = Bid;
      if (TakeProfit > 0) 
      {
         take = NormalizeDouble(price - (TakeProfit * Point), Digits);
         HiddenTakeProfit = take;         
      }//if (TakeProfit > 0) 
      

      if (HiddenPips > 0 && take > 0) take = NormalizeDouble(take - (HiddenPips * Point), Digits);

   }//if (type == OP_SELL)
   
   return(take);
   
}//End double CalculateTakeProfit(int type)

void LookForTradingOpportunities()
{


   RefreshRates();
   double take, stop, price;
   int type;
   string stype;//For the alert
   bool SendTrade;

   double SendLots = Lot;
   //Check filters
   if (!IsTradingAllowed() ) return;
   
   ////////////////////////////////////////////////////////////////////////////////////////////////////////
   //Trading decision.
   //Examine the filters one by one.
   //Work on the basis that a failed filter turns off SendLong/Short
   bool SendLong = true, SendShort = true;

   //Long trade
   
   //User choice of trade direction
   if (!TradeLong) SendLong = false;

   //Other filters
   
   ////////////////////////////////////////////////////////////////////////////////////////////
   //Short trade
   //Usual filters

   //User choice of trade direction
   if (!TradeShort) SendShort = false;
   
   //Other filters

////////////////////////////////////////////////////////////////////////////////////////////////////////
//DELETE THIS
SendLong = false; SendShort = false;
////////////////////////////////////////////////////////////////////////////////////////////////////////

   ////////////////////////////////////////////////////////////////////////////////////////////////////////
   
   
   //Long 
   if (SendLong)
   {
       
      //Got this far, so there is going to be a trade send of some sort. Setting up price here makes
      //this code most easily adaptable to easy alteration
      price = Ask;//Change this to whatever the price needs to be
      
      
      take = CalculateTakeProfit(OP_BUY);
      
      stop = CalculateStopLoss(OP_BUY);
      
      
      //Lot size calculated by risk
      if (RiskPercent > 0) SendLots = CalculateLotSize(price, NormalizeDouble(stop, Digits) );

      type = OP_BUY;
      stype = " Buy ";
      SendTrade = true;
   }//if (SendLong)
   
   //Short
   if (SendShort)
   {
      
      //Got this far, so there is going to be a trade send of some sort. Setting up price here makes
      //this code most easily adaptable to easy alteration
      price = Bid;//Change this to whatever the price needs to be

      take = CalculateTakeProfit(OP_SELL);
      
      stop = CalculateStopLoss(OP_SELL);
      
      
      //Lot size calculated by risk
      if (RiskPercent > 0) SendLots = CalculateLotSize(NormalizeDouble(stop, Digits), price);
      
      type = OP_SELL;
      stype = " Buy ";
      SendTrade = true;      
   }//if (SendShort)
   

   if (SendTrade)
   {
      bool result = SendSingleTrade(type, TradeComment, SendLots, price, stop, take);
   }//if (SendTrade)
   
   //Actions when trade send succeeds
   if (SendTrade && result)
   {
      if (HiddenPips > 0) ReplaceMissingSlTpLines();
   }//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


void CalculateDailyResult()
{
   //Calculate the no of winners and losers from today's trading. These are held in the history tab.

   LossTrades = 0;
   WinTrades = 0;
   OverallProfit = 0;
   
   
   for (int cc = 0; cc <= OrdersHistoryTotal(); cc++)
   {
      if (!OrderSelect(cc, SELECT_BY_POS, MODE_HISTORY) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderMagicNumber() != MagicNumber) continue;
      
      OverallProfit+= (OrderProfit() + OrderSwap() + OrderCommission() );
      if (OrderProfit() > 0) WinTrades++;
      if (OrderProfit() < 0) LossTrades++;
   }//for (int cc = 0; cc <= tot -1; cc++)
   
   

}//End void CalculateDailyResult()
   
double GetSlope(int tf, int shift)
{

   return(iCustom(NULL, tf, "10.2 TMA slope v.1.4B 4.30 for EA", 6, shift) );
   
}//End double GetSlope(int tf, int shift)

double GetWoh(int tf, int shift)
{

   //Up histo buffer
   double v = iCustom(NULL, tf, "10.2 WeeklyOpenHistogram 2x1 4.29", barsToProcess, 0, shift);
   if (v > 0) return(v);
   
   //Down histo buffer
   v = iCustom(NULL, tf, "10.2 WeeklyOpenHistogram 2x1 4.29", barsToProcess, 1, shift);
   if (v < 0) return(v);

   //Zero histo buffer. Not sure if this ever happens, but there is a buffer for it in the indi
   v = iCustom(NULL, tf, "10.2 WeeklyOpenHistogram 2x1 4.29", barsToProcess, 1, shift);
   if (CloseEnough(v, 0) ) return(0);

}//End double GetWoh(int tf, int shift)

void CalculatePivots()
{
   //Calculates the monthly and weekly pivots and their associated s/r levels.
   //Calculation code copied from 10.2 MonthlyMIDPivots.mq4

//double         MMR1, MR1, MMR2, MR2, MMR3, MR3, MMS1, MS1, MMS2, MS2, MMS3, MS3;//MonthlyMidResistance1. MonthlyResistance1 etc
   
   //Monthly
   double last_low=iLow(NULL, PERIOD_MN1, 1);
   double last_high=iHigh(NULL, PERIOD_MN1, 1);
   double last_close=iClose(NULL, PERIOD_MN1, 1);
 
   //Pivot and s/r lines
   double P=(last_high+last_low+last_close)/3;
   double R1=(2*P)-last_low;
   double S1=(2*P)-last_high;
   double R2=P+(last_high-last_low);
   double S2=P-(last_high-last_low);
   double R3=(2*P)+(last_high-(2*last_low));
   double S3=(2*P)-((2*last_high)-last_low);

 
   // calculate mid S/R lines		    
   double tMS3 = S3 + ((S2-S3) / 2);
   double tMS2 = S2 + ((S1-S2) / 2);
   double tMS1 = S1 + ((P-S1) / 2);
   double tMR1 = P + ((R1-P) / 2);
   double tMR2 = R1 + ((R2-R1) / 2);
   double tMR3 = R2 + ((R3-R2) / 2);
 
   //Copy the calculated values into their permanent variables.
   //MR1 = Monthly R1; MMR1 = Monthly Mid R1 etc.
   //It might be better to turn these into arrays. We shall see.
   MonthlyPivot = P;
   MR1 = R1;
   MMR1 = tMR1;
   MR2 = R2;
   MMR2 = tMR2;
   MR3 = R3;
   MMR3 = tMR3;
   
   MS1 = S1;
   MMS1 = tMS1;
   MS2 = S2;
   MMS2 = tMS2;
   MS3 = S3;
   MMS3 = tMS3;
   
   
   //Monthly
   last_low=iLow(NULL, PERIOD_W1, 1);
   last_high=iHigh(NULL, PERIOD_W1, 1);
   last_close=iClose(NULL, PERIOD_W1, 1);
 
   //Pivot and s/r lines
   P=(last_high+last_low+last_close)/3;
   WeeklyPivot = P;
   P=(last_high+last_low+last_close)/3;
   R1=(2*P)-last_low;
   S1=(2*P)-last_high;
   R2=P+(last_high-last_low);
   S2=P-(last_high-last_low);
   R3=(2*P)+(last_high-(2*last_low));
   S3=(2*P)-((2*last_high)-last_low);
   
   WR1 = R1;
   WR2 = R2;
   WR3 = R3;
   
   WS1 = S1;
   WS2 = S2;
   WS3 = S3;
   
   
}//End void CalculatePivots()

double GetMa(int tf, int period, int mashift, int method, int ap, int shift)
{
   return(iMA(NULL, tf, period, mashift, method, ap, shift) );
}//End double GetMa(int tf, int period, int mashift, int method, int ap, int shift)

void GetSupport(int tf)
{
   //Sets nearest support level on the passed time frame param

   //D1 support
   if (tf == PERIOD_D1)
   {
      D1Support = 0;
      
      if (Bid < MS3)
      {
         D1SupportText = " Below Monthly S3";
         return;
      }//if (Bid < MS3)
      
      if (Bid > MMS1)
      {
         D1SupportText = " Monthly mid S1";
         D1Support = MMS1;
         return;
      }//if (Bid > MMS1)
      
      if (Bid > MS1)
      {
         D1SupportText = " Monthly S1";
         D1Support = MS1;
         return;
      }//if (Bid > MMS1)
      
      if (Bid > MMS2)
      {
         D1SupportText = " Monthly mid S2";
         D1Support = MMS2;
         return;
      }//if (Bid > MMS1)
      
      if (Bid > MS2)
      {
         D1SupportText = " Monthly S2";
         D1Support = MS2;
         return;
      }//if (Bid > MMS1)
      
      if (Bid > MMS3)
      {
         D1SupportText = " Monthly mid S3";
         D1Support = MMS3;
         return;
      }//if (Bid > MMS3)
      
      if (Bid > MS3)
      {
         D1SupportText = " Monthly S3";
         D1Support = MS3;
         return;
      }//if (Bid > MMS3)
   }//if (tf == PERIOD_D1)
   
   //Any other timeframe
   if (Bid > WS1)
   {
         ChartSupportText = " Weekly S1";
         ChartSupport = WS1;
         return;      
   }//if (Bid > Ws1)
   
   if (Bid > WS2)
   {
         ChartSupportText = " Weekly S2";
         ChartSupport = WS2;
         return;      
   }//if (Bid > Ws2)
   
   if (Bid > WS3)
   {
         ChartSupportText = " Weekly S3";
         ChartSupport = WS3;
         return;      
   }//if (Bid > Ws1)
   
   
}//End void GetSupport(int tf)

void GetResistance(int tf)
{
   //Sets nearest resistance level on the passed time frame param
   
   //D1 resistance
   if (tf == PERIOD_D1)
   {
      D1Resistance = 0;
      
      if (Bid > MR3)
      {
         D1SupportText = " Above Monthly R3";
         return;
      }//if (Bid < MS3)
      
      if (Bid < MMR1)
      {
         D1ResistanceText = " Monthly mid R1";
         D1Resistance = MMR1;
         return;
      }//if (Bid < MMR1)
      
      if (Bid < MR1)
      {
         D1ResistanceText = " Monthly R1";
         D1Resistance = MR1;
         return;
      }//if (Bid < MMR1)
      
      if (Bid < MMR2)
      {
         D1ResistanceText = " Monthly mid R2";
         D1Resistance = MMR2;
         return;
      }//if (Bid < MMR1)
      
      if (Bid < MR2)
      {
         D1ResistanceText = " Monthly R2";
         D1Resistance = MR2;
         return;
      }//if (Bid < MMR1)
      
      if (Bid < MMR3)
      {
         D1ResistanceText = " Monthly mid R3";
         D1Resistance = MMR3;
         return;
      }//if (Bid < MMR3)
      
      if (Bid < MR3)
      {
         D1ResistanceText = " Monthly R3";
         D1Resistance = MR3;
         return;
      }//if (Bid < MMR3)
   }//if (tf == PERIOD_D1)
   
   //Any other timeframe
   if (Bid < WR1)
   {
         ChartResistanceText = " Weekly R1";
         ChartResistance = WR1;
         return;      
   }//if (Bid < WR1)
   
   if (Bid < WR2)
   {
         ChartResistanceText = " Weekly R2";
         ChartResistance = WR2;
         return;      
   }//if (Bid < WR2)
   
   if (Bid < WR3)
   {
         ChartResistanceText = " Weekly R3";
         ChartResistance = WR3;
         return;      
   }//if (Bid < WR1)
   
   
}//End void GetResistance(int tf)


void ReadIndicatorValues()
{
   //Called at the open of each M1 candle
   
   //Slope
   D1SlopeVal = GetSlope(PERIOD_D1, 0);
   D1SlopeTrend = ranging;
   if (D1SlopeVal >= 0.4) D1SlopeTrend = buyonly;
   if (D1SlopeVal <= -0.4) D1SlopeTrend = sellonly;
   if (D1SlopeVal >= 0.8) D1SlopeTrend = buyhold;
   if (D1SlopeVal <= -0.4) D1SlopeTrend = sellhold;

   //Calculate the angle
   static datetime OldD1BarTime;//Use this further down as well, so reset at the end of the function
   if (OldD1BarTime != iTime(NULL, PERIOD_D1, 0))
   {
      PrevD1SlopeVal = GetSlope(PERIOD_D1, 1);      
   }//if (OldD1BarTime != iTime(NULL, PERIOD_D1, 0)
   
   D1SlopeAngle = unchanged;
   if (D1SlopeVal  > PrevD1SlopeVal) D1SlopeAngle = rising;
   if (D1SlopeVal  < PrevD1SlopeVal) D1SlopeAngle = falling;
   

   if (Period() != PERIOD_D1)
   {
      ChartSlopeVal = GetSlope(Period(), 0);
      ChartSlopeTrend = ranging;
      if (ChartSlopeVal >= 0.4) ChartSlopeTrend = buyonly;
      if (ChartSlopeVal <= -0.4) ChartSlopeTrend = sellonly;
      if (ChartSlopeVal >= 0.8) ChartSlopeTrend = buyhold;
      if (ChartSlopeVal <= -0.4) ChartSlopeTrend = sellhold;

      static datetime OldChartBarTime;
      if (OldChartBarTime != iTime(NULL, Period(), 0))
      {
         PrevChartSlopeVal = GetSlope(Period(), 1);      
      }//if (OldChartBarTime != iTime(NULL, PERIOD_Chart, 0)
   
      ChartSlopeAngle = unchanged;
      if (ChartSlopeVal  > PrevChartSlopeVal) ChartSlopeAngle = rising;
      if (ChartSlopeVal  < PrevChartSlopeVal) ChartSlopeAngle = falling;
   }//if (Period() != PERIOD_D1)
   //Calculate the angle

   ///////////////////////////////////////////////////////////////////////////////////////////////
   
   //Woh trend
   D1WohVal = GetWoh(PERIOD_D1, 0);
   
   if (OldD1BarTime != iTime(NULL, PERIOD_D1, 0))
   {
      PrevD1WohVal = GetWoh(PERIOD_D1, 1);
   }//if (OldD1BarTime != iTime(NULL, PERIOD_D1, 0)

   D1WohTrend = none;
   if (D1WohVal > 0) D1WohTrend = up;
   if (D1WohVal < 0) D1WohTrend = down;
   D1WohAngle = unchanged;
   if (D1WohVal > PrevD1WohVal) D1WohAngle = rising;
   if (D1WohVal < PrevD1WohVal) D1WohAngle = falling;
   
   if (Period() != PERIOD_D1)
   {
      ChartWohVal = GetWoh(Period(), 0);
      ChartWohTrend = ranging;
      if (ChartWohVal > 0) ChartWohTrend = up;
      if (ChartWohVal < 0) ChartWohTrend = down;

      if (OldChartBarTime != iTime(NULL, Period(), 0))
      {
         PrevChartWohVal = GetWoh(Period(), 1);      
      }//if (OldChartBarTime != iTime(NULL, PERIOD_Chart, 0)
   
      ChartWohAngle = unchanged;
      if (ChartWohVal  > PrevChartWohVal) ChartWohAngle = rising;
      if (ChartWohVal  < PrevChartWohVal) ChartWohAngle = falling;
   }//if (Period() != PERIOD_D1)
   

   ///////////////////////////////////////////////////////////////////////////////////////////////
   //Direction of movement so far this week
   double wo = iMA(NULL,PERIOD_W1,1,0,MODE_SMA,PRICE_OPEN,0);
   double ma = iMA(NULL,0,1,0,MODE_SMA,PRICE_MEDIAN,0);
   WeeklyDirection = none;
   if (ma > wo) WeeklyDirection = up;
   if (ma < wo) WeeklyDirection = down;

   ///////////////////////////////////////////////////////////////////////////////////////////////
   //Pivots. Calculate at the start of each week
   static datetime OldPivotBarTime;
   if (OldPivotBarTime != iTime(NULL, PERIOD_W1, 0) )
   {
      OldPivotBarTime = iTime(NULL, PERIOD_W1, 0);
      CalculatePivots();
   }//if (OldPivotBarTime != iTime(NULL, PERIOD_W1, 0) )
   

   ///////////////////////////////////////////////////////////////////////////////////////////////
   //Moving averages
   D1BlueMaVal = GetMa(PERIOD_D1, MaPeriod, BlueMaShift, MaMethod, MaAppliedPrice, 0);
   D1GreenMaVal = GetMa(PERIOD_D1, MaPeriod, GreenMaShift, MaMethod, MaAppliedPrice, 0);
   D1MaroonMaVal = GetMa(PERIOD_D1, MaPeriod, MaroonMaShift, MaMethod, MaAppliedPrice, 0);
   
   ChartBlueMaVal = GetMa(0, MaPeriod, BlueMaShift, MaMethod, MaAppliedPrice, 0);
   ChartGreenMaVal = GetMa(0, MaPeriod, GreenMaShift, MaMethod, MaAppliedPrice, 0);
   ChartMaroonMaVal = GetMa(0, MaPeriod, MaroonMaShift, MaMethod, MaAppliedPrice, 0);
   
   ///////////////////////////////////////////////////////////////////////////////////////////////
   //Support/resistance
   GetSupport(PERIOD_D1);
   GetSupport(Period());
   GetResistance(PERIOD_D1);
   GetResistance(Period());
   ///////////////////////////////////////////////////////////////////////////////////////////////
   //Resets
   OldD1BarTime = iTime(NULL, PERIOD_D1, 0);
   OldChartBarTime = iTime(NULL, Period(), 0);
      
}//void ReadIndicatorValues()

//End Indicator module
////////////////////////////////////////////////////////////////////////////////////////////////

bool LookForTradeClosure(int ticket)
{
   //Close the trade if the close conditions are met.
   //Called from within CountOpenTrades(). Returns true if a close is needed and succeeds, so that COT can increment cc,
   //else returns false
   
   if (!OrderSelect(ticket, SELECT_BY_TICKET) ) return(true);
   if (OrderSelect(ticket, SELECT_BY_TICKET) && OrderCloseTime() > 0) return(true);
   
   bool CloseThisTrade;
   
   string LineName = TpPrefix + DoubleToStr(ticket, 0);
   //Work with the lines on the chart that represent the hidden tp/sl
   double take = ObjectGet(LineName, OBJPROP_PRICE1);
   LineName = SlPrefix + DoubleToStr(ticket, 0);
   double stop = ObjectGet(LineName, OBJPROP_PRICE1);
   
   if (OrderType() == OP_BUY)
   {
      //TP
      if (Bid >= take && take > 0) CloseThisTrade = true;
      //SL
      if (Bid <= stop && stop > 0) CloseThisTrade = true;

   }//if (OrderType() == OP_BUY)
   
   
   if (OrderType() == OP_SELL)
   {
      //TP
      if (Bid <= take && take > 0) CloseThisTrade = true;
      //SL
      if (Bid >= stop && stop > 0) CloseThisTrade = true;

   }//if (OrderType() == OP_SELL)
   
   if (CloseThisTrade)
   {
      bool result = CloseTrade(TicketNo);
      //Actions when trade close succeeds
      if (result)
      {
         DeletePendingPriceLines();
         TicketNo = -1;//TicketNo is the most recently trade opened, so this might need editing in a multi-trade EA
         OpenTrades--;//Rather than OpenTrades = 0 to cater for multi-trade EA's
         return(true);//Makes CountOpenTrades increment cc to avoid missing out ccounting a trade
      }//if (result)
   
      //Actions when trade close fails
      if (!result)
      {
         return(false);//Do not increment cc
      }//if (!result)
   }//if (CloseThisTrade)
   
   //Got this far, so no trade closure
   return(false);//Do not increment cc
   
}//End bool LookForTradeClosure()

void CloseAllTrades()
{
   ForceTradeClosure= false;
   
   if (OrdersTotal() == 0) return;
   
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderMagicNumber() != MagicNumber) continue;
      if (OrderSymbol() != Symbol() ) continue;
      while(IsTradeContextBusy()) Sleep(100);
      if (OrderType() == OP_BUY || OrderType() == OP_SELL) bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 1000, CLR_NONE);
      if (result) cc++;
      if (!result) ForceTradeClosure= true;
      
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)

   //If full closure succeeded, then allow new trading
   if (!ForceTradeClosure) 
   {
      OpenTrades = 0;
      BuyOpen = false;
      SellOpen = false;
   }//if (!ForceTradeClosure) 

}//End void CloseAllTrades()


bool CheckTradingTimes()
{
   //This code contributed by squalou. Many thanks, sq.
   
   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()

void CountOpenTrades()
{
   //Not all these will be needed. Which ones are depends on the individual EA.
   OpenTrades = 0;
   TicketNo = -1;
   BuyOpen = false;
   SellOpen = false;
   PendingBuyOpen = false;
   PendingSellOpen = false;
   int type;//Saves the OrderType() for consulatation later in the function
   
   upl = 0;//Unrealised profit and loss for hedging/recovery basket closure decisions

   if (OrdersTotal() == 0) return;
   
   //Iterating backwards through the orders list caters more easily for closed trades than iterating forwards
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      bool TradeWasClosed = false;//See 'check for possible trade closure'

      //Ensure the trade is still open
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      //Ensure the EA 'owns' this trade
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderMagicNumber() != MagicNumber) continue;
      
      //All conditions passed, so carry on
      type = OrderType();//Store the order type
      
      OpenTrades++;
      //Store the latest trade sent. Most of my EA's only need this final ticket number as either they are single trade
      //bots or the last trade in the sequence is the important one. Adapt this code for your own use.
      if (TicketNo  == -1) TicketNo = OrderTicket();
      
      //upl might not be needed. Depends on the individual EA
      upl+= (OrderProfit() + OrderSwap() + OrderCommission()); 
      //The next line of code calculates the pips upl of an open trade. As yet, I have done nothing with it.
      //something = CalculateTradeProfitInPips()
      
      //Trade types
      if (OrderType() == OP_BUY) BuyOpen = true;
      if (OrderType() == OP_SELL) SellOpen = true;
      //These might need extra coding if both stop and limit orders are used
      if (OrderType() == OP_BUYSTOP || OrderType() == OP_BUYLIMIT) PendingBuyOpen = true;
      if (OrderType() == OP_SELLSTOP || OrderType() == OP_SELLLIMIT) PendingSellOpen = true;
      //Add missing tp/sl in case rapidly moving markets prevent their addition - ECN
      if (OrderStopLoss() == 0 && StopLoss > 0) InsertStopLoss(TicketNo);
      if (OrderTakeProfit() == 0 && TakeProfit > 0) InsertTakeProfit(TicketNo);

      //Replace missing tp and sl lines
      if (HiddenPips > 0) ReplaceMissingSlTpLines();
      
      TradeWasClosed = LookForTradeClosure(OrderTicket() );
      if (TradeWasClosed) 
      {
         if (type == OP_BUY) BuyOpen = false;//Will be reset if subsequent trades are buys that are not closed
         if (type == OP_SELL) SellOpen = false;//Will be reset if subsequent trades are sells that are not closed
         cc++;
      }//if (TradeWasClosed) 
         
      //Profitable trade management
      if (OrderProfit() > 0 && !TradeWasClosed) TradeManagementModule();
      
   }//for (int cc = OrdersTotal() - 1; cc <= 0; c`c--)
   
   
   
}//End void CountOpenTrades();

void InsertStopLoss(int ticket)
{
   //Inserts a stop loss if the ECN crim managed to swindle the original trade out of the modification at trade send time
   //Called from CountOpenTrades() if StopLoss > 0 && OrderStopLoss() == 0.
   
   while(IsTradeContextBusy()) Sleep(100);
   if (!OrderSelect(ticket, SELECT_BY_TICKET) || OrderCloseTime() > 0) return;
   
   double stop;
   
   if (OrderType() == OP_BUY)
   {
      stop = CalculateStopLoss(OP_SELL);
   }//if (OrderType() == OP_BUY)
   
   if (OrderType() == OP_SELL)
   {
      stop = CalculateStopLoss(OP_SELL);
   }//if (OrderType() == OP_SELL)
   

   OrderModify(ticket, OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);

}//End void InsertStopLoss(int ticket)

void InsertTakeProfit(int ticket)
{
   //Inserts a TP if the ECN crim managed to swindle the original trade out of the modification at trade send time
   //Called from CountOpenTrades() if TakeProfit > 0 && OrderTakeProfit() == 0.
   
   while(IsTradeContextBusy()) Sleep(100);
   if (!OrderSelect(ticket, SELECT_BY_TICKET) || OrderCloseTime() > 0) return;
   
   double take;
   
   if (OrderType() == OP_BUY)
   {
      take = CalculateTakeProfit(OP_BUY);
   }//if (OrderType() == OP_BUY)
   
   if (OrderType() == OP_SELL)
   {
      take = CalculateTakeProfit(OP_SELL);
   }//if (OrderType() == OP_SELL)
   

   OrderModify(ticket, OrderOpenPrice(), OrderStopLoss(), take, OrderExpiration(), CLR_NONE);

}//End void InsertStopLoss(int ticket)




///////////////////////////////////////////////////////////////////////////////////////////////////////
//Pending trade price lines module.
//Doubles up by providing missing lines for the stealth stuff
void DrawPendingPriceLines()
{
   //This function will work for a full pending-trade EA.
   //The pending tp/sl can be used for hiding the stops in a market-trading ea
   
   /*
   ObjectDelete(pendingpriceline);
   ObjectCreate(pendingpriceline, OBJ_HLINE, 0, TimeCurrent(), PendingPrice);
   if (PendingBuy) ObjectSet(pendingpriceline, OBJPROP_COLOR, Green);
   if (PendingSell) ObjectSet(pendingpriceline, OBJPROP_COLOR, Red);
   ObjectSet(pendingpriceline, OBJPROP_WIDTH, 1);
   ObjectSet(pendingpriceline, OBJPROP_STYLE, STYLE_DASH);
   */
   string LineName = TpPrefix + DoubleToStr(TicketNo, 0);//TicketNo is set by the calling function - either CountOpenTrades or DoesTradeExist
   HiddenTakeProfit = 0;
   if (TicketNo > -1 && OrderTakeProfit() > 0)
   {
      if (OrderType() == OP_BUY || OrderType() == OP_BUYSTOP || OrderType() == OP_BUYLIMIT)
      {
         HiddenTakeProfit = NormalizeDouble(OrderTakeProfit() - (HiddenPips * Point), Digits);
      }//if (OrderType() == OP_BUY)
      
      if (OrderType() == OP_SELL)
      {
         HiddenTakeProfit = NormalizeDouble(OrderTakeProfit() + (HiddenPips * Point), Digits);
      }//if (OrderType() == OP_BUY)      
   }//if (TicketNo > -1 && OrderTakeProfit() > 0)
   
   if (HiddenTakeProfit > 0 && ObjectFind(LineName) == -1)
   {
      ObjectDelete(LineName);
      ObjectCreate(LineName, OBJ_HLINE, 0, TimeCurrent(), HiddenTakeProfit);
      ObjectSet(LineName, OBJPROP_COLOR, Green);
      ObjectSet(LineName, OBJPROP_WIDTH, 1);
      ObjectSet(LineName, OBJPROP_STYLE, STYLE_DOT);
   }//if (HiddenTakeProfit > 0)
   
   
   LineName = SlPrefix + DoubleToStr(TicketNo, 0);//TicketNo is set by the calling function - either CountOpenTrades or DoesTradeExist
   HiddenStopLoss = 0;
   if (TicketNo > -1 && OrderStopLoss() > 0)
   {
      if (OrderType() == OP_BUY)
      {
         HiddenStopLoss = NormalizeDouble(OrderStopLoss() + (HiddenPips * Point), Digits);
      }//if (OrderType() == OP_BUY)
      
      if (OrderType() == OP_SELL || OrderType() == OP_SELLSTOP || OrderType() == OP_SELLLIMIT)
      {
         HiddenStopLoss = NormalizeDouble(OrderStopLoss() - (HiddenPips * Point), Digits);
      }//if (OrderType() == OP_BUY)      
   }//if (TicketNo > -1 && OrderStopLoss() > 0)
   
   if (HiddenStopLoss > 0 && ObjectFind(LineName) == -1)
   {
      ObjectDelete(LineName);
      ObjectCreate(LineName, OBJ_HLINE, 0, TimeCurrent(), HiddenStopLoss);
      ObjectSet(LineName, OBJPROP_COLOR, Red);
      ObjectSet(LineName, OBJPROP_WIDTH, 1);
      ObjectSet(LineName, OBJPROP_STYLE, STYLE_DOT);
   }//if (HiddenStopLoss > 0)
   
   

}//End void DrawPendingPriceLines()


void DeletePendingPriceLines()
{

   
   //ObjectDelete(pendingpriceline);
   string LineName = TpPrefix + DoubleToStr(TicketNo, 0);
   ObjectDelete(LineName);
   LineName = SlPrefix + DoubleToStr(TicketNo, 0);
   ObjectDelete(LineName);
   
}//End void DeletePendingPriceLines()

void ReplaceMissingSlTpLines()
{

   if (OrderTakeProfit() > 0 || OrderStopLoss() > 0) DrawPendingPriceLines();

}//End void ReplaceMissingSlTpLines()

void DeleteOrphanTpSlLines()
{

   if (ObjectsTotal() == 0) return;
   
   for (int cc = ObjectsTotal() - 1; cc >= 0; cc--)
   {
      string name = ObjectName(cc);
      
      if ((StringSubstr(name, 0, 2) == TpPrefix || StringSubstr(name, 0, 2) == SlPrefix) && ObjectType(name) == OBJ_HLINE)
      {
         int tn = StrToDouble(StringSubstr(name, 2));
         if (tn > 0) 
         {
            if (!OrderSelect(tn, SELECT_BY_TICKET, MODE_TRADES) || OrderCloseTime() > 0)
            {
               ObjectDelete(name);
            }//if (!OrderSelect(tn, SELECT_BY_TICKET, MODE_TRADES) || OrderCloseTime() > 0)
            
         }//if (tn > 0) 
         
         
      }//if (StringSubstr(name, 0, 1) == TpPrefix)
      
   }//for (int cc = ObjectsTotal() - 1; cc >= 0; cc--)
   
   
}//End void DeleteOrphanTpSlLines()


//END Pending trade price lines module
///////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////
//TRADE MANAGEMENT MODULE

void ReportError()
{
   //All purpose sl mod error reporter. Called when a sl mod fails
   
   int err=GetLastError();
      
   Alert(OrderTicket()," stop loss modification failed with error(",err,"): ",ErrorDescription(err));
   Print(OrderTicket()," stop loss modification failed with error(",err,"): ",ErrorDescription(err));      

}//void ReportError()



void BreakEvenStopLoss() // Move stop loss to breakeven
{

   double NewStop;
   bool result;
   bool modify=false;
   string LineName = SlPrefix + DoubleToStr(OrderTicket(), 0);
   double sl = ObjectGet(LineName, OBJPROP_PRICE1);
   
   if (OrderType()==OP_BUY)
   {
      if (OrderStopLoss() >= OrderOpenPrice() - (HiddenPips * Point) ) return;
      if (Bid >= OrderOpenPrice () + (Point*BreakEvenPips))          
      {
         //Calculate the new stop
         NewStop = NormalizeDouble(OrderOpenPrice()+(BreakEvenProfit*Point), Digits);
         if (HiddenPips > 0)
         {
            if (ObjectFind(LineName) == -1)
            {
               ObjectCreate(LineName, OBJ_HLINE, 0, TimeCurrent(), 0);
               ObjectSet(LineName, OBJPROP_COLOR, Red);
               ObjectSet(LineName, OBJPROP_WIDTH, 1);
               ObjectSet(LineName, OBJPROP_STYLE, STYLE_DOT);
            }//if (ObjectFind(LineName == -1) )
         
            ObjectMove(LineName, 0, TimeCurrent(), NewStop);         
         }//if (HiddenPips > 0)
         modify = true;   
      }//if (Bid >= OrderOpenPrice () + (Point*BreakEvenPips) && 
   }//if (OrderType()==OP_BUY)               			         
    
   if (OrderType()==OP_SELL)
   {
     if ((OrderStopLoss() <= OrderOpenPrice() + (HiddenPips * Point) ) && OrderStopLoss() > 0) return;
     if (Ask <= OrderOpenPrice() - (Point*BreakEvenPips)) 
     {
         //Calculate the new stop
         NewStop = NormalizeDouble(OrderOpenPrice()-(BreakEvenProfit*Point), Digits);
         if (HiddenPips > 0)
         {
            if (ObjectFind(LineName) == -1)
            {
               ObjectCreate(LineName, OBJ_HLINE, 0, TimeCurrent(), 0);
               ObjectSet(LineName, OBJPROP_COLOR, Red);
               ObjectSet(LineName, OBJPROP_WIDTH, 1);
               ObjectSet(LineName, OBJPROP_STYLE, STYLE_DOT);
            }//if (ObjectFind(LineName == -1) )
         
            ObjectMove(LineName, 0, Time[0], NewStop);
         }//if (HiddenPips > 0)         
         modify = true;   
     }//if (Ask <= OrderOpenPrice() - (Point*BreakEvenPips) && (OrderStopLoss()>OrderOpenPrice()|| OrderStopLoss()==0))     
   }//if (OrderType()==OP_SELL)

   //Move 'hard' stop loss whether hidden or not. Don't want to risk losing a breakeven through disconnect.
   if (modify)
   {
      if (NewStop == OrderStopLoss() ) return;
      while (IsTradeContextBusy() ) Sleep(100);
      result = OrderModify(OrderTicket(), OrderOpenPrice(), NewStop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);      
      if (!result) ReportError();
   }//if (modify)
   
} // End BreakevenStopLoss sub

void JumpingStopLoss() 
{
   // Jump sl by pips and at intervals chosen by user .

   //if (OrderProfit() < 0) return;//Nothing to do
   string LineName = SlPrefix + DoubleToStr(OrderTicket(), 0);
   double sl = ObjectGet(LineName, OBJPROP_PRICE1);
   
   //if (sl == 0) return;//No line, so nothing to do
   double NewStop;
   bool modify=false;
   bool result;
   
   
    if (OrderType()==OP_BUY)
    {
       //if (sl < OrderOpenPrice() ) return;//Not at breakeven yet
       // Increment sl by sl + JumpingStopPips.
       // This will happen when market price >= (sl + JumpingStopPips)
       //if (Bid>= sl + ((JumpingStopPips*2)*Point) )
       sl = MathMax(sl, OrderOpenPrice());
       if (Bid >=  sl + ((JumpingStopPips * 2) * Point) )//George{
       {
          NewStop = NormalizeDouble(sl + (JumpingStopPips * Point), Digits);
          if (AddBEP) NewStop = NormalizeDouble(NewStop + (BreakEvenProfit*Point), Digits);
          if (HiddenPips > 0) ObjectMove(LineName, 0, Time[0], NewStop);
          if (NewStop - OrderStopLoss() >= Point) modify = true;//George again. What a guy
       }// if (Bid>= sl + (JumpingStopPips*Point) && sl>= OrderOpenPrice())     
    }//if (OrderType()==OP_BUY)
       
       if (OrderType()==OP_SELL)
       {
          //if (sl > OrderOpenPrice() ) return;//Not at breakeven yet
          // Decrement sl by sl - JumpingStopPips.
          // This will happen when market price <= (sl - JumpingStopPips)
          //if (Bid<= sl - ((JumpingStopPips*2)*Point)) Original code
          sl = MathMin(sl, OrderOpenPrice());
          if (sl == 0) sl = OrderOpenPrice();
          if (Bid <= sl - ((JumpingStopPips * 2) * Point) )//George
          {
             NewStop = NormalizeDouble(sl - (JumpingStopPips * Point), Digits);
             if (AddBEP) NewStop = NormalizeDouble(NewStop - (BreakEvenProfit*Point), Digits);
             if (HiddenPips > 0) ObjectMove(LineName, 0, Time[0], NewStop);
             if (OrderStopLoss() - NewStop >= Point || OrderStopLoss() == 0) modify = true;//George again. What a guy   
          }// close if (Bid>= sl + (JumpingStopPips*Point) && sl>= OrderOpenPrice())         
       }//if (OrderType()==OP_SELL)



   //Move 'hard' stop loss whether hidden or not. Don't want to risk losing a breakeven through disconnect.
   if (modify)
   {
      while (IsTradeContextBusy() ) Sleep(100);
      result = OrderModify(OrderTicket(), OrderOpenPrice(), NewStop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);      
      if (!result) ReportError();      
   }//if (modify)

} //End of JumpingStopLoss sub


void TrailingStopLoss()
{
   
   if (OrderProfit() < 0) return;//Nothing to do
   string LineName = SlPrefix + DoubleToStr(OrderTicket(), 0);
   double sl = ObjectGet(LineName, OBJPROP_PRICE1);
   //if (sl == 0) return;//No line, so nothing to do
   double NewStop;
   bool modify=false;
   bool result;
   
    if (OrderType()==OP_BUY)
       {
          //if (sl < OrderOpenPrice() ) return;//Not at breakeven yet
          // Increment sl by sl + TrailingStopPips.
          // This will happen when market price >= (sl + JumpingStopPips)
          //if (Bid>= sl + (TrailingStopPips * Point) ) Original code
          sl = MathMax(sl, OrderOpenPrice());
          if (Bid >= sl + (TrailingStopPips * Point) )//George
          {
             NewStop = NormalizeDouble(sl + (TrailingStopPips * Point), Digits);
             if (HiddenPips > 0) ObjectMove(LineName, 0, Time[0], NewStop);
             if (NewStop - OrderStopLoss() >= Point) modify = true;//George again. What a guy
          }//if (Bid >= MathMax(sl,OrderOpenPrice()) + (TrailingStopPips * Point) )//George
       }//if (OrderType()==OP_BUY)
       
       if (OrderType()==OP_SELL)
       {
          //if (sl > OrderOpenPrice() ) return;//Not at breakeven yet
          // Decrement sl by sl - TrailingStopPips.
          // This will happen when market price <= (sl - JumpingStopPips)
          //if (Bid<= sl - (TrailingStopPips * Point) ) Original code
          sl = MathMin(sl, OrderOpenPrice());
          if (sl == 0) sl = OrderOpenPrice();
          if (Bid <= sl  - (TrailingStopPips * Point))//George
          {
             NewStop = NormalizeDouble(sl - (TrailingStopPips * Point), Digits);
             if (HiddenPips > 0) ObjectMove(LineName, 0, Time[0], NewStop);
             if (OrderStopLoss() - NewStop >= Point || OrderStopLoss() == 0) modify = true;//George again. What a guy   
          }//if (Bid <= MathMin(sl, OrderOpenPrice() ) - (TrailingStopPips * Point) )//George
       }//if (OrderType()==OP_SELL)


   //Move 'hard' stop loss whether hidden or not. Don't want to risk losing a breakeven through disconnect.
   if (modify)
   {
      while (IsTradeContextBusy() ) Sleep(100);
      result = OrderModify(OrderTicket(), OrderOpenPrice(), NewStop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);      
      if (!result) ReportError();
   }//if (modify)
      
} // End of TrailingStopLoss sub

void CandlestickTrailingStop()
{
   
   //Trails the stop at the hi/lo of the previous candle shifted by the user choice.
   //Only tries to do this once per bar, so an invalid stop error will only be generated once. I could code for
   //a too-close sl, but cannot be arsed. Coders, sort this out for yourselves.
   
   if (OldCstBars == iBars(NULL, CstTimeFrame)) return;
   OldCstBars = iBars(NULL, CstTimeFrame);

   if (OrderProfit() < 0) return;//Nothing to do
   string LineName = SlPrefix + DoubleToStr(OrderTicket(), 0);
   double sl = ObjectGet(LineName, OBJPROP_PRICE1);
   if (sl == 0) return;//No line, so nothing to do
   double NewStop;
   bool modify=false;
   bool result;
   

   if (OrderType() == OP_BUY)
   {
      if (iLow(NULL, CstTimeFrame, CstTrailCandles) > sl)
      {
         NewStop = NormalizeDouble(iLow(NULL, CstTimeFrame, CstTrailCandles), Digits);
         if (HiddenPips > 0) 
         {
            ObjectMove(LineName, 0, Time[0], NewStop);
            NewStop = NormalizeDouble(NewStop - (HiddenPips * Point), Digits);
         }//if (HiddenPips > 0) 
         modify = true;   
      }//if (iLow(NULL, CstTimeFrame, CstTrailCandles) > sl)
   }//if (OrderType == OP_BUY)
   
   if (OrderType() == OP_SELL)
   {
      if (iHigh(NULL, CstTimeFrame, CstTrailCandles) < sl)
      {
         NewStop = NormalizeDouble(iHigh(NULL, CstTimeFrame, CstTrailCandles), Digits);
         if (HiddenPips > 0) 
         {
            ObjectMove(LineName, 0, Time[0], NewStop);
            NewStop = NormalizeDouble(NewStop + (HiddenPips * Point), Digits);
         }//if (HiddenPips > 0) 
         modify = true;   
      }//if (iHigh(NULL, CstTimeFrame, CstTrailCandles) < sl)
   }//if (OrderType() == OP_SELL)
   
   //Move 'hard' stop loss whether hidden or not. Don't want to risk losing a breakeven through disconnect.
   if (modify)
   {
      while (IsTradeContextBusy() ) Sleep(100);
      result = OrderModify(OrderTicket(), OrderOpenPrice(), NewStop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);      
      if (!result) ReportError();
   }//if (modify)

}//End void CandlestickTrailingStop()


void TradeManagementModule()
{

   // Call the working subroutines one by one. 

   //Candlestick trailing stop
   if (UseCandlestickTrailingStop) CandlestickTrailingStop();


   // Breakeven
   if(BreakEven) BreakEvenStopLoss();

   // JumpingStop
   if(JumpingStop) JumpingStopLoss();

   //TrailingStop
   if(TrailingStop) TrailingStopLoss();

   

}//void TradeManagementModule()
//END TRADE MANAGEMENT MODULE
////////////////////////////////////////////////////////////////////////////////////////////////



double CalculateTradeProfitInPips()
{
   //This function returns the profit/loss of an individual trade in pips. The function is called from
   //within CountTrades(), so the trade is already selected

   double Pips;
   
   //This returns Pips as a whole number
   Pips = (OrderProfit() / OrderLots()) / MarketInfo(OrderSymbol(),MODE_TICKVALUE);

   double digits = MarketInfo(OrderSymbol(), MODE_DIGITS);
   int multiplier;
   if (digits == 2) multiplier = 10;
   if (digits == 3) multiplier = 100;
   if (digits == 4) multiplier = 1000;
   if (digits == 5) multiplier = 10000;
   
   //This returns Pips as a decimal number i.e. Pips * Point
   //Pips = (OrderProfit() / OrderLots()) / MarketInfo(OrderSymbol(),MODE_TICKVALUE) / multiplier;

   return(Pips);

}//double CalculateTradeProfitInPips()

bool CloseEnough(double num1, double num2)
{
   /*
   This function addresses the problem of the way in which mql4 compares doubles. It often messes up the 8th
   decimal point.
   For example, if A = 1.5 and B = 1.5, then these numbers are clearly equal. Unseen by the coder, mql4 may
   actually be giving B the value of 1.50000001, and so the variable are not equal, even though they are.
   This nice little quirk explains some of the problems I have endured in the past when comparing doubles. This
   is common to a lot of program languages, so watch out for it if you program elsewhere.
   Gary (garyfritz) offered this solution, so our thanks to him.
   */
   
   if (MathAbs(num1 - num2) < 0.0001) return(true);//Doubles are equal
   
   //Doubles are unequal
   return(false);

}//End bool CloseEnough(double num1, double num2)


//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
//----

   
   
   /*
   People get twitchy when reading the code being removed from the ex4 file warning, so here is a neat method of
   turning off a function without deleting it, just in case you change your mind and want it later. I actually call
   CalculateTradeProfitInPips() from within CountOpenTrades() and include it here merely as an example.
   */
   if (TurnOff == 1) CalculateTradeProfitInPips();//TurnOff is never 1, so the function is not called
   
   if (OrdersTotal() == 0)
   {
      TicketNo = -1;
      ForceTradeClosure = false;
   }//if (OrdersTotal() == 0)


   if (ForceTradeClosure) 
   {
      CloseAllTrades();
      return;
   }//if (ForceTradeClosure) 

   //Read the indi's once a minute
   static datetime OldM1BarTime;
   if (EveryTickMode) OldM1BarTime = 0;
   if (OldM1BarTime != iTime(NULL, IndiReadTimeFrame, 0) )
   {
      OldM1BarTime = iTime(NULL, IndiReadTimeFrame, 0);
      ReadIndicatorValues();
   }//if (OldM1BarTime != iTime(NULL, PERIOD_M1, 0)
   
   
   
   //Daily results so far - they work on what in in the history tab, so users need warning that
   //what they see displayed on screen depends on that.   
   //Code courtesy of TIG yet again. Thanks, George.
   static int OldHistoryTotal;
   if (OrdersHistoryTotal() != OldHistoryTotal)
   {
      CalculateDailyResult();//Does no harm to have a recalc from time to time
      OldHistoryTotal = OrdersHistoryTotal();
   }//if (OrdersHistoryTotal() != OldHistoryTotal)
   
   
   //Delete orphaned tp/sl lines
   static int M15Bars;
   if (M15Bars != iBars(NULL, PERIOD_M15) )
   {
      M15Bars = iBars(NULL, PERIOD_M15);
      DeleteOrphanTpSlLines();
   }//if (M15Bars != iBars(NULL, PERIOD_M15)
   
      
   ///////////////////////////////////////////////////////////////////////////////////////////////
   //Find open trades.
   if (TurnOff == 1) CountOpenTrades();//No need to call the function in a data-gathering EA

   //Reset various bools
   if (OpenTrades == 0)
   {

   }//if (OpenTrades > 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 (!TradeTimeOk)
   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////


   ///////////////////////////////////////////////////////////////////////////////////////////////         
   //Trading
      
   if (TicketNo == -1 && !StopTrading)
   {
      
      LookForTradingOpportunities();
   }//if (TicketNo == -1)
   ///////////////////////////////////////////////////////////////////////////////////////////////      

   DisplayUserFeedback();
   
//----
   return(0);
}
//+------------------------------------------------------------------+

