//+-------------------------------------------------------------------+
//|                                                           Pas.mq4 |
//|                                    Copyright 2012, Steve Hopwood  |
//|                              http://www.hopwood3.freeserve.co.uk  |
//+-------------------------------------------------------------------+

#define  version "Version 1b"

#property copyright "Copyright 2012, 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"

//Colour constants for previous candle colour
#define  green "Green"
#define  red "Red"

//Pending trade lines
#define  buyline "Pending buy line"
#define  sellline "Pending sell line"

//Currency status
#define  upaccelerating "Up, and accelerating"
#define  updecelerating "Up, but slowing"
#define  downaccelerating "Down, and accelerating"
#define  downdecelerating "Down, but slowing"

//Pending trade price line
#define  pendingpriceline "Pending price line"
//Hidden sl and tp lines. If used, 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"

//RSI TMA Slope constants
#define  pinhigh "Pin high"
#define  pinlow "Pin low"
#define  pinnone "No pin"

//Slope constants
#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. "

//Error reporting
#define  slm " stop loss modification failed with error "
#define  tpm " take profit modification failed with error "
#define  ocm " order close failed with error "
#define  odm " order delete failed with error "
#define  pcm " part close failed with error "

/*
  
  
Matt Kennel has provided the code for bool O_R_CheckForHistory(int ticket). Cheers Matt, You are a star.

The support and resistance library code used in this EA is supplied by slipshod (Andrew Sumner). Andrew, we are deeply indebted to you for this. Latest versions of SS_SupportResistance.mq4 and the library code are found at http://www.stevehopwoodforex.com/phpBB3/viewtopic.php?f=27&t=514

Code for adding debugging Sleep
Alert("G");
int x = 0;
while (x == 0) Sleep(100);

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);

To calculate what percentage a small number is of a larger one:
(Given amount Divided by Total amount) x100 = %
as in UpperWickPercentage = (UpperWick / CandleSize) * 100; where CandleSize is the size of the the candle and UpperWick the size of the top of the body to the High.

Example of iHighest and iLowest
double lastHigh = iHigh( symbolNames[i], PERIOD_H1, iHighest( symbolNames[i], PERIOD_H1, MODE_HIGH, 24, 1 ) );
double lastLow = iLow( symbolNames[i], PERIOD_H1, iLowest( symbolNames[i], PERIOD_H1, MODE_LOW, 24, 1 ) );

   Full snippet to force closure of all open trades. Use whichever part is most appropriate.
   if (ForceTradeClosure)
   {
      CloseAllTrades();
      if (ForceTradeClosure)
      {
         CloseAllTrades();
         if (ForceTradeClosure)
         {
            return;
         }//if (ForceTradeClosure)                     
      }//if (ForceTradeClosure)         
   }//if (ForceTradeClosure)      

*/

extern string   gen="----General inputs----";
extern double   Lot=0.01;
extern double   RiskPercent = 0;//Set to zero to disable and use Lot
extern bool     StopTrading=false;
extern bool     TradeLong=true;
extern bool     TradeShort=true;
extern int      TakeProfitPips=0;
extern int      StopLossPips=0;
extern int      MagicNumber=1243;
extern string   TradeComment="Pas";
extern bool     IsGlobalPrimeOrECNCriminal=false;
extern double   MaxSlippagePips=5;
bool     EveryTickMode=false;
////////////////////////////////////////////////////////////////////////////////////////
double          TakeProfit, StopLoss;
datetime        OldBarsTime;
////////////////////////////////////////////////////////////////////////////////////////

extern string   sep1="----------------------------------------------------------------";
extern string   pas="----Specific Pas inputs----";
extern string   tfs="--Time frames--";
extern int      TF1=60;//Longest tf
extern int      TF2=30;//Next tf down
extern int      TF3=15;//Next tf down
extern int      TF4=5;//Next tf down
extern string   lin="----Pending trade lines----";
extern color    BuyLineColour=Green;
extern color    SellLineColour=Red;
extern int      LineDeletionMinutes=50;// OrderExpiration() time sent with the pending trade
extern int      PendingPriceBufferPips=3;//Above/below the close of the previous TF1 candle
extern string   buf="--Buffer and multipliers--";
extern int      StopLossBufferPips=2;//Above/below the hilo of the previous TF1 candle
extern double   TakeProfitMultiplier=2;//Multiplies the auto-calculated SL by this to produce TakeProfit
////////////////////////////////////////////////////////////////////////////////////////
string          Tf1Colour, Tf2Colour, Tf3Colour, Tf4Colour;//Colours of the previous TF1 etc candles
double          PendingPriceBuffer;//doubles converterfor PendingPriceBufferPips
double          StopLossBuffer;//doubles converterfor StopLossBufferPips
////////////////////////////////////////////////////////////////////////////////////////

extern string   sep1a="----------------------------------------------------------------";
extern string   sfs="----SafetyFeature----";
//Safety feature. Sometimes an unexpected concatenation of inputs choice and logic error can cause rapid opening-closing of trades. Use the next input in combination with TooClose() to abort the trade if the porevious one closed within the time limit.

extern int      MinMinutesBetweenTrades=0;
extern int      MinMinutesBetweenTradeOpenClose=0;
////////////////////////////////////////////////////////////////////////////////////////
bool            SafetyViolation;//For chart display
bool            RobotSuspended=false;
////////////////////////////////////////////////////////////////////////////////////////

extern string   sep2="----------------------------------------------------------------";
//Hidden tp/sl inputs.
extern string   hts="----Stealth stop loss and take profit inputs----";
extern int      PipsHiddenFromCriminal=0;//Added to the 'hard' sl and tp and used for closure calculations
////////////////////////////////////////////////////////////////////////////////////////
double          HiddenStopLoss, HiddenTakeProfit;
double          HiddenPips=0;//Added to the 'hard' sl and tp and used for closure calculations
////////////////////////////////////////////////////////////////////////////////////////


extern string   sep3="----------------------------------------------------------------";
//Bob's H4 240 trend filter. Market above the ma = buy only; below ma = sell only
extern string   mai="--Moving average--";
extern int      MaTF=240;
extern int      MaPeriod=0;//Zero value to disable
int      MaShift=0;//The MA Shift input
extern string   mame="Method: 0=sma; 1=ema; 2=smma;  3=lwma";
extern int      MaMethod=0;
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;
////////////////////////////////////////////////////////////////////////////////////////
double          MaVal;
string          MaTrend;//up, down or none constants
////////////////////////////////////////////////////////////////////////////////////////

extern string    sep4="----------------------------------------------------------------";
extern string   slo="----Slope inputs----";
extern int      HtfTimeFrame=0;//Zero to disable
extern double   HtfBuyOnlyLevel=0.4;
extern double   HtfBuyHoldLevel=0.8;
extern double   HtfBuyCloseLevel=0.3;
extern double   HtfSellOnlyLevel=-0.4;
extern double   HtfSellHoldLevel=-0.8;
extern double   HtfSellCloseLevel=-0.3;
extern int      LtfTimeFrame=0;//Zero to disable
extern double   LtfBuyOnlyLevel=0.4;
extern double   LtfBuyHoldLevel=0.8;
extern double   LtfBuyCloseLevel=0.3;
extern double   LtfSellOnlyLevel=-0.4;
extern double   LtfSellHoldLevel=-0.8;
extern double   LtfSellCloseLevel=-0.3;////////////////////////////////////////////////////////////////////////////////////////
double          HtfSlopeVal, LtfSlopeVal, PrevHtfSlopeVal, PrevLtfSlopeVal;
string          HtfSlopeTrend, LtfSlopeTrend, HtfSlopeAngle, LtfSlopeAngle;
////////////////////////////////////////////////////////////////////////////////////////

extern string   sep5="----------------------------------------------------------------";
extern string	 CSS_Input="----CCS inputs----";
extern bool     UseCSS=false;
extern int      maxBars           = 100;
extern int      CssTf=0;//Defaults to current time frame
// extern bool     ignoreFuture      = true;
string          CurrNames[8]  = { "USD", "EUR", "GBP", "CHF", "JPY", "AUD", "CAD", "NZD" };
////////////////////////////////////////////////////////////////////////////////////////
string          Curr1, Curr2;//First and second currency in the pair
int             CurrIndex1, CurrIndex2;//Index of the currencies that form the pair to point to the correct one in currencyNames
double          CurrVal1[3], CurrVal2[3];//Hold the values of the two currencies, alloing me to look back in time to see if the currency is rising or falling.
string          CurrDirection1, CurrDirection2;//One of the Currency ststus constants
////////////////////////////////////////////////////////////////////////////////////////

extern string   sep6="----------------------------------------------------------------";
extern string   rst="----RSI-TMA Slope indi inputs----";
extern bool     UseTmaRsi2=false;
extern int      TmaRsi2TF=0;//Defaults to current tf
extern int      PinHighLevel=90;//Sell after a pin high
extern int      PinLowLevel=10;//Buy after a pin low
////////////////////////////////////////////////////////////////////////////////////////
double          RsiTmaVal[4];
string          RsiPinStatus;//Will be one of the pin constants pinhigh, pinlow or pinnone
////////////////////////////////////////////////////////////////////////////////////////

extern string   sep7="----------------------------------------------------------------";
//CheckTradingTimes. Baluda has provided all the code for this. Mny thanks Paul; you are a star.
extern string	trh				= "----Trading hours----";
extern string	tr1				= "tradingHours is a comma delimited list";
extern string   tr1a            = "of start and stop times.";
extern string	tr2				= "Prefix start with '+', stop with '-'";
extern string   tr2a            = "Use 24H format, local time.";
extern string	tr3				= "Example: '+07.00,-10.30,+14.15,-16.00'";
extern string	tr3a			= "Do not leave spaces";
extern string	tr4				= "Blank input means 24 hour trading.";
extern string	tradingHours="";
////////////////////////////////////////////////////////////////////////////////////////
double	        TradeTimeOn[];
double	        TradeTimeOff[];
// trading hours variables
int 	        tradeHours[];
string          tradingHoursDisplay;//tradingHours is reduced to "" on initTradingHours, so this variable saves it for screen display.
bool            TradeTimeOk;
////////////////////////////////////////////////////////////////////////////////////////

extern string   sep8="----------------------------------------------------------------";
extern string   bf="----Trading balance filters----";
extern bool     UseZeljko=false;
extern bool     OnlyTradeCurrencyTwice=false;
////////////////////////////////////////////////////////////////////////////////////////
bool            CanTradeThisPair;
////////////////////////////////////////////////////////////////////////////////////////

extern string   sep9="----------------------------------------------------------------";
extern string   pts="----Swap filter----";
extern bool     CadPairsPositiveOnly=false;
extern bool     AudPairsPositiveOnly=false;
extern bool     NzdPairsPositiveOnly=false;
extern bool     OnlyTradePositiveSwap=false;
////////////////////////////////////////////////////////////////////////////////////////
double          LongSwap, ShortSwap;
////////////////////////////////////////////////////////////////////////////////////////

extern string   sep10="----------------------------------------------------------------";
extern string   amc="----Available Margin checks----";
extern string   sco="Scoobs";
extern bool     UseScoobsMarginCheck=false;
extern string   fk="ForexKiwi";
extern bool     UseForexKiwi=false;
extern int      FkMinimumMarginPercent=1500;
////////////////////////////////////////////////////////////////////////////////////////
bool           EnoughMargin;
string         MarginMessage;
////////////////////////////////////////////////////////////////////////////////////////

extern string   sep11="----------------------------------------------------------------";
extern string   asi="----Average spread inputs----";
extern bool     RunInSpreadDetectionMode=false;
extern int      TicksToCount=200;//The ticks to count whilst canculating the av spread
extern double   MultiplierToDetectStopHunt=10;
////////////////////////////////////////////////////////////////////////////////////////
double          AverageSpread=0;
string          SpreadGvName;//A GV will hold the calculated average spread
int             CountedTicks=0;//For status display whilst calculating the spread
double          BiggestSpread=0;//Holds a record of the widest spread since the EA was loaded
////////////////////////////////////////////////////////////////////////////////////////

extern string   sep12="----------------------------------------------------------------";
extern string   ems="----Email thingies----";
extern bool     EmailTradeNotification=false;
extern bool     SendAlertNotTrade=false;
extern bool     AlertPush=false;// Enable to send push notification on alert
////////////////////////////////////////////////////////////////////////////////////////
bool            AlertSent;//To alert to a trade trigger without actually sending the trade
////////////////////////////////////////////////////////////////////////////////////////

extern string   sep13="----------------------------------------------------------------";
extern string   tmm="----Trade management module----";
//Breakeven has to be enabled for JS and TS to work.
extern string   BE="Break even settings";
extern bool     BreakEven=true;
extern int      BreakEvenTargetPips=15;
extern int      BreakEvenTargetProfit=5;
extern bool     PartCloseEnabled=false;
extern double   PartClosePercent=50;//Percentage of the trade lots to close
////////////////////////////////////////////////////////////////////////////////////////
double          BreakEvenPips, BreakEvenProfit;
bool            TradeHasPartClosed=false;
////////////////////////////////////////////////////////////////////////////////////////

extern string   sep14="----------------------------------------------------------------";
extern string   JSL="Jumping stop loss settings";
extern bool     JumpingStop=false;
extern int      JumpingStopTargetPips=10;
extern bool     AddBEP=true;
////////////////////////////////////////////////////////////////////////////////////////
double          JumpingStopPips;
////////////////////////////////////////////////////////////////////////////////////////

extern string   sep15="----------------------------------------------------------------";
extern string   cts="----Candlestick jumping stop----";
extern bool     UseCandlestickTrailingStop=false;
extern int      CstTimeFrame=0;//Defaults to current chart
extern int      CstTrailCandles=1;//Defaults to previous candle
extern bool     TrailMustLockInProfit=true;
////////////////////////////////////////////////////////////////////////////////////////
int             OldCstBars;//For candlestick ts
////////////////////////////////////////////////////////////////////////////////////////

extern string   sep16="----------------------------------------------------------------";
extern string   TSL="Trailing stop loss settings";
extern bool     TrailingStop=false;
extern int      TrailingStopTargetPips=20;
////////////////////////////////////////////////////////////////////////////////////////
double          TrailingStopPips;
////////////////////////////////////////////////////////////////////////////////////////

extern string   sep17="----------------------------------------------------------------";
extern string   mis="----Odds and ends----";
extern int      DisplayGapSize=30;
////////////////////////////////////////////////////////////////////////////////////////
string          Gap, ScreenMessage;
////////////////////////////////////////////////////////////////////////////////////////

//Calculating the factor needed to turn pip values into their correct points value to accommodate different Digit size.
//Thanks to Lifesys for providing this code. Coders, you need to briefly turn of Wrap and turn on a mono-spaced font to view this properly and see how easy it is to make changes.
string          pipFactor[]  = {"JPY","XAG","SILVER","BRENT","WTI","XAU","GOLD","SP500","S&P","UK100","WS30","DAX30","DJ30","NAS100","CAC400"};
double          pipFactors[] = { 100,  100,  100,     100,    100,  10,   10,    10,     10,   1,      1,     1,      1,     1,       1};
double          factor;//For pips/points stuff. Set up in int init()
////////////////////////////////////////////////////////////////////////////////////////


//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, OldOpenTrades;
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);
   SM(NL);
   if (SafetyViolation) SM("*************** CANNOT TRADE YET. TOO SOON AFTER CLOSE OF PREVIOUS TRADE***************" + NL);
   
   SM("Updates for this EA are to be found at http://www.stevehopwoodforex.com" + NL);
   SM("Feeling generous? Help keep the coder going with a small Paypal donation to pianodoodler@hotmail.com" + NL);
   SM("Broker time = " + TimeToStr(TimeCurrent(), TIME_DATE|TIME_SECONDS) + ": Local time = " + TimeToStr(TimeLocal(), TIME_DATE|TIME_SECONDS) + NL );
   SM(version + NL);
   /*
   //Code for time to bar-end display from Candle Time by Nick Bilak
   double i;
   int m +s +k;
   m=Time[0]+Period()*60-CurTime();
   i=m/60.0;
   s=m%60;
   m=(m-m%60)/60;
   SM(m + " minutes " + s + " seconds left to bar end" + NL);
   */
   if (!TradeTimeOk)
   {
      SM(NL);
      SM("----------OUTSIDE TRADING HOURS. Will continue to monitor opent trades.----------" + NL + NL);
   }//if (!TradeTimeOk)

   SM(NL);     
   SM("Previous candle colours:" + NL);
   SM("      M" + DoubleToStr(TF1, 0) + ": " + Tf1Colour + NL);
   SM("      M" + DoubleToStr(TF2, 0) + ": " + Tf2Colour + NL);
   SM("      M" + DoubleToStr(TF3, 0) + ": " + Tf3Colour + NL);
   SM("      M" + DoubleToStr(TF4, 0) + ": " + Tf4Colour + NL);
   

   if (UseCSS)
   {
      SM(Curr1 + " = " + DoubleToStr(CurrVal1[2], 2) + "  "  + DoubleToStr(CurrVal1[1], 2) + ": Direction is " + CurrDirection1 + NL);
      SM(Curr2 + " = " + DoubleToStr(CurrVal2[2], 2) + "  "  + DoubleToStr(CurrVal2[1], 2) + ": Direction is " + CurrDirection2 + NL);
   }//if (UseCSS)
   
   if (UseTmaRsi2)
   {
      string RsiDisplay = "RSI TMA Slope = ";
      for (int cc = 3; cc >= 0; cc--)
      {
         RsiDisplay = StringConcatenate(RsiDisplay, DoubleToStr(RsiTmaVal[cc], 4), ": ");
      }//for (cc = 3; cc >= 0; cc--)   
      SM(RsiDisplay + NL);
      SM("RSI TMA Slope pin status: " + RsiPinStatus + NL);
   }//if (UseTmaRsi2)
   
   if (MaPeriod > 0) SM("Moving average = " + DoubleToStr(MaVal, Digits) + ": Trend is " + MaTrend + NL);
   if (HtfTimeFrame > 0)
   {
      SM("Htf value " + DoubleToStr(HtfSlopeVal, 4) + ": Trend is " + HtfSlopeTrend + NL);
      //SM("Htf value " + DoubleToStr(HtfSlopeVal, 4) + ": Trend is " + HtfSlopeTrend + HtfSlopeAngle + NL);                                                                
   }//if (HtfTimeFrame > 0)

   if (LtfTimeFrame > 0)
   {
      SM("Ltf value " + DoubleToStr(LtfSlopeVal, 4) + ": Trend is " + LtfSlopeTrend + NL);
      //SM("Ltf value " + DoubleToStr(LtfSlopeVal, 4) + ": Trend is " + LtfSlopeTrend + LtfSlopeAngle + NL);
   }//if (LtfTimeFrame > 0)

   SM(NL);     
   if (TradeLong) SM("Taking long trades" + NL);
   if (TradeShort) SM("Taking short trades" + NL);
   if (!TradeLong && !TradeShort) SM("Both TradeLong and TradeShort are set to false" + NL);
   SM("Lot size: " + DoubleToStr(Lot, 2) + " (Criminal's minimum lot size: " + DoubleToStr(MarketInfo(Symbol(), MODE_MINLOT) , 2)+ ")" + NL);
   if (!CloseEnough(TakeProfit, 0)) SM("Take profit: " + DoubleToStr(TakeProfit, 0) + PipDescription +  NL);
   if (!CloseEnough(StopLoss, 0)) SM("Stop loss: " + DoubleToStr(StopLoss, 0) + PipDescription +  NL);
   SM("Magic number: " + MagicNumber + NL);
   SM("Trade comment: " + TradeComment + NL);
   if (IsGlobalPrimeOrECNCriminal) SM("IsGlobalPrimeOrECNCriminal = true" + NL);
   else SM("IsGlobalPrimeOrECNCriminal = false" + NL);
   double spread = (Ask - Bid) * factor;   
   SM("Average Spread = " + DoubleToStr(AverageSpread, 1) + ": Spread = " + DoubleToStr(spread, 1) + ": Widest since loading = " + DoubleToStr(BiggestSpread, 1) + NL);
   SM("Long swap " + DoubleToStr(LongSwap, 2) + ": ShortSwap " + DoubleToStr(ShortSwap, 2) + NL);
   SM(NL);
   
   //Trading hours
   if (tradingHoursDisplay != "") SM("Trading hours: " + tradingHoursDisplay + NL);
   else SM("24 hour trading: " + NL);
   
   if (MarginMessage != "") SM(MarginMessage + NL);


   //Running total of trades
   SM(Gap + NL);
   SM("Results today. Wins: " + WinTrades + ": Losses " + LossTrades + ": P/L " + DoubleToStr(OverallProfit, 2) + NL);
   
      
   SM(NL);
   
   if (BreakEven)
   {
      SM("Breakeven is set to " + DoubleToStr(BreakEvenPips, 0) + PipDescription + ": BreakEvenProfit = " + DoubleToStr(BreakEvenProfit, 0) + PipDescription);
      SM(NL);
      if (PartCloseEnabled)
      {
         double CloseLots = NormalizeLots(Symbol(),Lot * (PartClosePercent / 100));
         SM("Part-close is enabled at " + DoubleToStr(PartClosePercent, 2) + "% (" + DoubleToStr(CloseLots, 2) + " lots to close)" + NL);
      }//if (PartCloseEnabled)      
   }//if (BreakEven)

   if (UseCandlestickTrailingStop)
   {
      SM("Using candlestick trailing stop" + NL);      
   }//if (UseCandlestickTrailingStop)
   
   if (JumpingStop)
   {
      SM("Jumping stop is set to " + DoubleToStr(JumpingStopPips, 0) + PipDescription);
      SM(NL);  
   }//if (JumpingStop)
   

   if (TrailingStop)
   {
      SM("Trailing stop is set to " + DoubleToStr(TrailingStopPips, 0) + PipDescription);
      SM(NL);  
   }//if (TrailingStop)
   
   
   
   Comment(ScreenMessage);


}//void DisplayUserFeedback()

void SM(string message)
{
   
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, message);
      
}//End void DM()

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
//----


   //~ Set up the pips factor. tp and sl etc.
   //~ The EA uses doubles and assume the value of the integer user inputs. This: 
   //~    1) minimises the danger of the inputs becoming corrupted by restarts; 
   //~    2) the integer inputs cannot be divided by factor - doing so results in zero.
   
   factor = PFactor(Symbol());
   StopLoss = StopLossPips;
   TakeProfit = TakeProfitPips;
   BreakEvenPips = BreakEvenTargetPips;
   BreakEvenProfit = BreakEvenTargetProfit;
   JumpingStopPips = JumpingStopTargetPips;
   TrailingStopPips = TrailingStopTargetPips;
   HiddenPips = PipsHiddenFromCriminal;
   PendingPriceBuffer = PendingPriceBufferPips;
   StopLossBuffer = StopLossBufferPips;
   
   while (IsConnected()==false)
   {
      Comment("Waiting for MT4 connection...");
      Sleep(1000);
   }//while (IsConnected()==false)

   //Lot size and part-close idiot check for the cretins. Code provided by phil_trade. Many thanks, Philippe.
   //adjust Min_lot
   if (Lot < MarketInfo(Symbol(), MODE_MINLOT)) 
   {
   Alert(Symbol()+" Lot was adjusted to Minlot = "+DoubleToStr(MarketInfo(Symbol(), MODE_MINLOT),Digits ) );
   Lot = MarketInfo(Symbol(), MODE_MINLOT);
   }//if (Lot < MarketInfo(Symbol(), MODE_MINLOT)) 
   /*
   //check Partial close parameters
   if (PartCloseEnabled == true)
   {
      if (Lot < Close_Lots + Preserve_Lots || Lot < MarketInfo(Symbol(), MODE_MINLOT) + Close_Lots )
      {
         Alert(Symbol()+" PartCloseEnabled is disabled because Lot < Close_Lots + Preserve_Lots or Lot < MarketInfo(Symbol(), MODE_MINLOT) + Close_Lots !");
         PartCloseEnabled = false;
      }//if (Lot < Close_Lots + Preserve_Lots || Lot < MarketInfo(Symbol(), MODE_MINLOT) + Close_Lots )
   }//if (PartCloseEnabled == true)
   */

   //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) IsGlobalPrimeOrECNCriminal = true;   
   ispart = StringFind(name, "Global Prime", 0);
   if (ispart > -1) IsGlobalPrimeOrECNCriminal = true;   
   
   //Set up the trading hours
   tradingHoursDisplay = tradingHours;//For display
   initTradingHours();//Sets up the trading hours array

   // Initialize libCSS
   libCSSinit();

   if (TradeComment == "") TradeComment = " ";
   OldBars = Bars;
   TicketNo = -1;
   ReadIndicatorValues();//For initial display in case user has turned of constant re-display
   GetSwap(Symbol());//This will need editing/removing in a multi-pair ea.
   TradeDirectionBySwap();
   TooClose();
   CountOpenTrades();
   OldOpenTrades = OpenTrades;
   TradeTimeOk = CheckTradingTimes();   
   //The apread global variable
   SpreadGvName = Symbol() + " average spread";
   AverageSpread = GlobalVariableGet(SpreadGvName);//If no gv, then the value will be left at zero.
   
   OldBarsTime = iTime(NULL, TF1, 0);   
   DisplayUserFeedback();

   
   
   //Call sq's show trades indi
   //iCustom(NULL, 0, "SQ_showTrades",Magic, 0,0);

   
//----
   return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
//----
   Comment("");
   DeleteLines();

   
//----
   return(0);
}

void DeleteLines()
{
   if (ObjectFind(0, buyline) > -1)
      ObjectDelete(buyline);
   if (ObjectFind(0, sellline) > -1)
      ObjectDelete(sellline);
      

}//End void DeleteLines()

bool SendSingleTrade(string symbol, 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.
   
   double slippage = MaxSlippagePips * MathPow(10, Digits) / PFactor(Symbol());

   
   
   color col = Red;
   if (type == OP_BUY || type == OP_BUYSTOP) col = Green;
   
   datetime expiry = 0;
  
   //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);

      while(IsTradeContextBusy()) Sleep(100);//Put here so that excess slippage will cancel the trade if the ea has to wait for some time.

      RefreshRates();
      if (type == OP_BUY) price = MarketInfo(symbol, MODE_ASK);
      if (type == OP_SELL) price = MarketInfo(symbol, MODE_BID);
      
      
      if (!IsGlobalPrimeOrECNCriminal) int ticket = OrderSend(symbol,type, lotsize, price, slippage, stop, take, comment, MagicNumber, expiry, col);
   
   
      //Is a 2 stage criminal
      if (IsGlobalPrimeOrECNCriminal)
      {
         ticket = OrderSend(symbol, type, lotsize, price, slippage, 0, 0, comment, MagicNumber, expiry, col);
         if (ticket > -1)
         {
	           ModifyOrder(ticket, stop, take);
         }//if (ticket > 0)}
      }//if (IsGlobalPrimeOrECNCriminal)
      
      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 (CloseEnough(stop, 0) && CloseEnough(take, 0) ) return; //nothing to do

   if (!OrderSelect(ticket, SELECT_BY_TICKET) ) return;//Trade does not exist, so no mod needed
   
   if (OrderCloseTime() > 0) return;//Somehow, we are examining a closed trade
   
   //In case some errant behaviour/code creates a tp the wrong side of the market, which would cause an instant close.
   if (OrderType() == OP_BUY && take < OrderOpenPrice() && !CloseEnough(take, 0) ) 
   {
      take = 0;
      ReportError(" ModifyOrder()", " take profit < market ");
   }//if (OrderType() == OP_BUY && take < OrderOpenPrice() ) 
   
   if (OrderType() == OP_SELL && take > OrderOpenPrice() ) 
   {
      take = 0;
      ReportError(" ModifyOrder()", " take profit < market ");
   }//if (OrderType() == OP_SELL && take > OrderOpenPrice() ) 
   
   //In case some errant behaviour/code creates a sl the wrong side of the market, which would cause an instant close.
   if (OrderType() == OP_BUY && stop > OrderOpenPrice() ) 
   {
      stop = 0;
      ReportError(" ModifyOrder()", " stop loss > market ");
   }//if (OrderType() == OP_BUY && take < OrderOpenPrice() ) 
   
   if (OrderType() == OP_SELL && stop < OrderOpenPrice()  && !CloseEnough(stop, 0) ) 
   {
      stop = 0;
      ReportError(" ModifyOrder()", " stop loss < market ");
   }//if (OrderType() == OP_SELL && take > OrderOpenPrice() ) 
   
   string Reason;
   //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 (!CloseEnough(take, 0) && !CloseEnough(stop, 0) )
        {
           while(IsTradeContextBusy()) Sleep(100);
           if (OrderModify(ticket, OrderOpenPrice(), stop, take, OrderExpiration(), CLR_NONE)) return;
           Reason = " TP or SL modification failed with error ";//For error report
        }//if (take > 0 && stop > 0)
   
        if (!CloseEnough(take, 0) && CloseEnough(stop, 0))
        {
           while(IsTradeContextBusy()) Sleep(100);
           if (OrderModify(ticket, OrderOpenPrice(), OrderStopLoss(), take, OrderExpiration(), CLR_NONE)) return;
           Reason = tpm;//For error report
        }//if (take == 0 && stop != 0)

        if (CloseEnough(take, 0) && !CloseEnough(stop, 0))
        {
           while(IsTradeContextBusy()) Sleep(100);
           if (OrderModify(ticket, OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE)) return;
           Reason = slm;//For error report
        }//if (take == 0 && stop != 0)
   }//for (int cc = 0; cc < RetryCount; cc++)
   
   //Got this far, so the order modify failed
   ReportError(" ModifyOrder()", Reason);
   
}//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 (!IsDemo() )
   {
      double spread = (Ask - Bid) * factor;
      if (spread > AverageSpread * MultiplierToDetectStopHunt) return(false);
   }//if (!IsDemo() )
   
    
   //An individual currency can only be traded twice, so check for this
   CanTradeThisPair = true;
   if (OnlyTradeCurrencyTwice && OpenTrades == 0)
   {
      IsThisPairTradable();      
   }//if (OnlyTradeCurrencyTwice)
   if (!CanTradeThisPair) return(false);
   
   //Swap filter
   if (OpenTrades == 0) TradeDirectionBySwap();
   
   //Order close time safety feature
   if (TooClose()) return(false);

   return(true);


}//End bool IsTradingAllowed()

////////////////////////////////////////////////////////////////////////////////////////
//Balance/swap filters module
void TradeDirectionBySwap()
{

   //Sets TradeLong & TradeShort according to the positive/negative swap it attracts

   //Swap is read in init() and start()


   if (CadPairsPositiveOnly)
   {
      if (StringSubstrOld(Symbol(), 0, 3) == "CAD" || StringSubstrOld(Symbol(), 0, 3) == "cad" || StringSubstrOld(Symbol(), 3, 3) == "CAD" || StringSubstrOld(Symbol(), 3, 3) == "cad" )      
      {
         if (LongSwap > 0) TradeLong = true;
         else TradeLong = false;
         if (ShortSwap > 0) TradeShort = true;
         else TradeShort = false;         
      }//if (StringSubstrOld()      
   }//if (CadPairsPositiveOnly)
   
   if (AudPairsPositiveOnly)
   {
      if (StringSubstrOld(Symbol(), 0, 3) == "AUD" || StringSubstrOld(Symbol(), 0, 3) == "aud" || StringSubstrOld(Symbol(), 3, 3) == "AUD" || StringSubstrOld(Symbol(), 3, 3) == "aud" )      
      {
         if (LongSwap > 0) TradeLong = true;
         else TradeLong = false;
         if (ShortSwap > 0) TradeShort = true;
         else TradeShort = false;         
      }//if (StringSubstrOld()      
   }//if (AudPairsPositiveOnly)
   
   
   if (NzdPairsPositiveOnly)
   {
      if (StringSubstrOld(Symbol(), 0, 3) == "NZD" || StringSubstrOld(Symbol(), 0, 3) == "nzd" || StringSubstrOld(Symbol(), 3, 3) == "NZD" || StringSubstrOld(Symbol(), 3, 3) == "nzd" )      
      {
         if (LongSwap > 0) TradeLong = true;
         else TradeLong = false;
         if (ShortSwap > 0) TradeShort = true;
         else TradeShort = false;         
      }//if (StringSubstrOld()      
   }//if (AudPairsPositiveOnly)
   
   //OnlyTradePositiveSwap filter
   if (OnlyTradePositiveSwap)
   {
      if (LongSwap < 0) TradeLong = false;
      if (ShortSwap < 0) TradeShort = false;      
   }//if (OnlyTradePositiveSwap)
   

}//void TradeDirectionBySwap()

bool IsThisPairTradable()
{
   //Checks to see if either of the currencies in the pair is already being traded twice.
   //If not, then return true to show that the pair can be traded, else return false
   
   string c1 = StringSubstrOld(Symbol(), 0, 3);//First currency in the pair
   string c2 = StringSubstrOld(Symbol(), 3, 3);//Second currency in the pair
   int c1open = 0, c2open = 0;
   CanTradeThisPair = true;
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderMagicNumber() != MagicNumber) continue;
      int index = StringFind(OrderSymbol(), c1);
      if (index > -1)
      {
         c1open++;         
      }//if (index > -1)
   
      index = StringFind(OrderSymbol(), c2);
      if (index > -1)
      {
         c2open++;         
      }//if (index > -1)
   
      if (c1open == 1 && c2open == 1) 
      {
         CanTradeThisPair = false;
         return(false);   
      }//if (c1open == 1 && c2open == 1) 
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)

   //Got this far, so ok to trade
   return(true);
   
}//End bool IsThisPairTradable()

bool BalancedPair(int type)
{

   //Only allow an individual currency to trade if it is a balanced trade
   //e.g. UJ Buy open, so only allow Sell xxxJPY.
   //The passed parameter is the proposed trade, so an existing one must balance that

   //This code courtesy of Zeljko (zkucera) who has my grateful appreciation.
   
   string BuyCcy1, SellCcy1, BuyCcy2, SellCcy2;

   if (type == OP_BUY || type == OP_BUYSTOP)
   {
      BuyCcy1 = StringSubstrOld(Symbol(), 0, 3);
      SellCcy1 = StringSubstrOld(Symbol(), 3, 3);
   }//if (type == OP_BUY || type == OP_BUYSTOP)
   else
   {
      BuyCcy1 = StringSubstrOld(Symbol(), 3, 3);
      SellCcy1 = StringSubstrOld(Symbol(), 0, 3);
   }//else

   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS)) continue;
      if (OrderSymbol() == Symbol()) continue;
      if (OrderMagicNumber() != MagicNumber) continue;      
      if (OrderType() == OP_BUY || OrderType() == OP_BUYSTOP)
      {
         BuyCcy2 = StringSubstrOld(OrderSymbol(), 0, 3);
         SellCcy2 = StringSubstrOld(OrderSymbol(), 3, 3);
      }//if (OrderType() == OP_BUY || OrderType() == OP_BUYSTOP)
      else
      {
         BuyCcy2 = StringSubstrOld(OrderSymbol(), 3, 3);
         SellCcy2 = StringSubstrOld(OrderSymbol(), 0, 3);
      }//else
      if (BuyCcy1 == BuyCcy2 || SellCcy1 == SellCcy2) return(false);
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)

   //Got this far, so it is ok to send the trade
   return(true);

}//End bool BalancedPair(int type)



//End Balance/swap filters module
////////////////////////////////////////////////////////////////////////////////////////
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;//No idea why *= factor does not work here, but it doesn't
   
   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, double price)
{
   //Returns the stop loss for use in LookForTradingOpps and InsertMissingStopLoss
   double stop;
   
   
   RefreshRates();
   
   if (type == OP_BUY)
   {
      //Autocalculate stop loss pips
      if (StopLossPips == 0)
      {
         StopLoss = (price - iLow(Symbol(), TF1, 1)) * factor;
         StopLoss-= StopLossBuffer;
      }//if (StopLossPips == 0)
      
      if (!CloseEnough(StopLoss, 0) ) 
      {
         stop = price - (StopLoss / factor);
         HiddenStopLoss = stop;
      }//if (!CloseEnough(StopLoss, 0) ) 

      if (HiddenPips > 0 && stop > 0) stop = NormalizeDouble(stop - (HiddenPips / factor), Digits);
   }//if (type == OP_BUY)
   
   if (type == OP_SELL)
   {
      
      //Autocalculate stop loss pips
      if (StopLossPips == 0)
      {
         StopLoss = (price + iLow(Symbol(), TF1, 1)) * factor;
         StopLoss+= StopLossBuffer;
      }//if (StopLossPips == 0)
      
      if (!CloseEnough(StopLoss, 0) ) 
      {
         stop = price + (StopLoss / factor);
         HiddenStopLoss = stop;         
      }//if (!CloseEnough(StopLoss, 0) ) 
      
      if (HiddenPips > 0 && stop > 0) stop = NormalizeDouble(stop + (HiddenPips / factor), Digits);

   }//if (type == OP_SELL)
   
   return(stop);
   
}//End double CalculateStopLoss(int type)

double CalculateTakeProfit(int type, double price)
{
   //Returns the stop loss for use in LookForTradingOpps and InsertMissingStopLoss
   double take;
   
   //If the user is allowing the ea to calculate stop loss and take profit
   if (TakeProfitPips == 0)
      TakeProfit = (StopLoss * TakeProfitMultiplier);
      
   RefreshRates();
   
   if (type == OP_BUY)
   {
      if (!CloseEnough(TakeProfit, 0) )
      {
         take = price + (TakeProfit / factor);
         HiddenTakeProfit = take;
      }//if (!CloseEnough(TakeProfit, 0) )

               
      if (HiddenPips > 0 && take > 0) take = NormalizeDouble(take + (HiddenPips / factor), Digits);

   }//if (type == OP_BUY)
   
   if (type == OP_SELL)
   {
      if (!CloseEnough(TakeProfit, 0) )
      {
         take = price - (TakeProfit / factor);
         HiddenTakeProfit = take;         
      }//if (!CloseEnough(TakeProfit, 0) )
      
      
      if (HiddenPips > 0 && take > 0) take = NormalizeDouble(take - (HiddenPips / factor), Digits);

   }//if (type == OP_SELL)
   
   return(take);
   
}//End double CalculateTakeProfit(int type)

void LookForTradingOpportunities()
{


   RefreshRates();
   double price;
   string stype;//For the alert
   bool SendTrade = false, result = false;

   double SendLots = Lot;
   //Check filters
   if (!IsTradingAllowed() ) return;
   
   
   /////////////////////////////////////////////////////////////////////////////////////
   
   //Trading decision.
   bool SendLong = false, SendShort = false;

   //Long trade
   
   //Specific system filters
   if (Tf1Colour == green)
      if (Tf2Colour == green)
         if (Tf4Colour == green)
            if (Tf4Colour == green)            
               SendLong = true;
   
   //Usual filters
   if (SendLong)
   {
      //User choice of trade direction
      if (!TradeLong) return;
      
      //Bob's 240 H4 ma trend filter
      if (MaPeriod > 0)
         if (MaTrend != up)
            return;

      //CSS.         
      if (UseCSS)
      {
         //We are buying the first in the pair ans selling the second, so ensure they are moving in the correct direction and on the right side of 0
         if (CurrDirection1 == downaccelerating || CurrDirection1 == downdecelerating) return;
         if (CurrDirection2 == upaccelerating || CurrDirection2 == updecelerating) return;
      }//if (UseCSS)
      
      //Other filters
      //Slope must be in the buy area
      if (HtfTimeFrame > 0 && HtfSlopeVal < HtfBuyOnlyLevel) return;
      if (LtfTimeFrame > 0 && LtfSlopeVal < LtfBuyOnlyLevel) return;
      
      if (UseZeljko && !BalancedPair(OP_BUY) ) return;
      
      //Change of market state - explanation at the end of start()
      //if (OldAsk <= some_condition) SendLong = false;   
   }//if (SendLong)
   
   /////////////////////////////////////////////////////////////////////////////////////

   if (!SendLong)
   {
      //Short trade
      //Specific system filters
      if (Tf1Colour == red)
         if (Tf2Colour == red)
            if (Tf4Colour == red)
               if (Tf4Colour == red)            
                  SendShort = true;
      
      
      if (SendShort)
      {      
         //Usual filters

         //User choice of trade direction
         if (!TradeShort) return;
         
         //Bob's 240 H4 ma trend filter
         if (MaPeriod > 0)
            if (MaTrend != down)
               return;

         //Other filters
         //CSS.         
         if (UseCSS)
         {
            //We are selling the first in the pair ans buying the second, so ensure they are moving in the correct direction and on the right side of 0        
            if (CurrDirection1 == upaccelerating || CurrDirection1 == updecelerating) return;
            if (CurrDirection2 == downaccelerating || CurrDirection2 == downdecelerating) return;
         }//if (UseCSS)

         //Slope must be in the sell area
         if (HtfTimeFrame > 0 && HtfSlopeVal > HtfSellOnlyLevel) return;
         if (LtfTimeFrame > 0 && LtfSlopeVal > LtfSellOnlyLevel) return;
         
         if (UseZeljko && !BalancedPair(OP_SELL) ) return;
         
         //Change of market state - explanation at the end of start()
         //if (OldBid += some_condition) SendShort = false;   
      }//if (SendShort)
      
   }//if (!SendLong)
     

////////////////////////////////////////////////////////////////////////////////////////
   
   
   //Long 
   if (SendLong)
   {
       
      price = NormalizeDouble(iClose(Symbol(), TF1, 1) + (PendingPriceBuffer / factor), Digits);//Change this to whatever the price needs to be
      DrawHorizontalLine(buyline, price, BuyLineColour, STYLE_DASH, 0);

           
   }//if (SendLong)
   
   //Short
   if (SendShort)
   {
      price = NormalizeDouble(iClose(Symbol(), TF1, 1) - (PendingPriceBuffer / factor), Digits);//Change this to whatever the price needs to be
      DrawHorizontalLine(sellline, price, SellLineColour, STYLE_DASH, 0);
      
   }//if (SendShort)
   
}//void LookForTradingOpportunities()

void HasBuyFilled()
{
   //Called if start() finds a buy line
   double take = 0, stop = 0, price = 0;
   int type = 0;
   string stype = "";//For the alert
   bool result = false;
   double SendLots = Lot;
   
   double target = ObjectGet(buyline, OBJPROP_PRICE1);
   
   RefreshRates();
   
   if (Ask >= target)
   {
      stype = " Buy";
      price = NormalizeDouble(iClose(Symbol(), TF1, 1) + (PendingPriceBuffer / factor), Digits);//Change this to whatever the price needs to be
         
      if (!SendAlertNotTrade)
      {
         
         stop = CalculateStopLoss(OP_BUY, price);
         
         
         take = CalculateTakeProfit(OP_BUY, price);
         
         
         //Lot size calculated by risk
         if (RiskPercent > 0) SendLots = CalculateLotSize(price, NormalizeDouble(stop + (HiddenPips / factor), Digits) );

         type = OP_BUY;
         
         if (!SendAlertNotTrade) 
         { 
            result = SendSingleTrade(Symbol(), type, TradeComment, SendLots, price, stop, take);
            if (result) 
            {
               ObjectDelete(0, buyline);
               if (EmailTradeNotification) SendMail("Trade sent ", Symbol() + stype + "trade at " + TimeToStr(TimeCurrent(), TIME_DATE|TIME_MINUTES));
               if (AlertPush) AlertNow(WindowExpertName() + " " + Symbol() + " " + stype + " " + DoubleToStr(price, Digits) );
               OrderSelect(TicketNo, SELECT_BY_TICKET, MODE_TRADES);
               CheckTpSlAreCorrect(type);
            }//if (result)          
         }//if (!SendAlertNotTrade) 
         
         if (SendAlertNotTrade && !AlertSent)
         {
            Alert(WindowExpertName(), " ", Symbol(), " ", stype, "trade has triggered. ",  TimeToStr(TimeLocal(), TIME_DATE|TIME_MINUTES|TIME_SECONDS) );
            SendMail("Trade alert. ", Symbol() + " " + stype + " trade has triggered. " +  TimeToStr(TimeLocal(), TIME_DATE|TIME_MINUTES|TIME_SECONDS ));
            if (AlertPush) AlertNow(WindowExpertName() + " " + Symbol() + " " + stype + " " + DoubleToStr(price, Digits) );         
            AlertSent=true;
          }//if (SendAlertNotTrade && !AlertSent)
      }//if (!SendAlertNotTrade)
      
      //Actions when trade send succeeds
      if (result)
      {      
         if (!SendAlertNotTrade && !CloseEnough(HiddenPips, 0) ) ReplaceMissingSlTpLines();
      }//if (result)
      
      //Actions when trade send fails
      if (!result)
      {
         OldBarsTime = 0;
      }//if (!result)
         
   }//if (Ask >= target)
   

}//End void HasBuyFilled

void HasSellFilled()
{
   //Called if start() finds a buy line
   double take = 0, stop = 0, price = 0;
   int type = 0;
   string stype = "";//For the alert
   bool result = false;
   double SendLots = Lot;
   
   double target = ObjectGet(sellline, OBJPROP_PRICE1);
   
   RefreshRates();
   
   if (Bid <= target)
   {
      stype = " Sell";
      price = NormalizeDouble(iClose(Symbol(), TF1, 1) - (PendingPriceBuffer / factor), Digits);//Change this to whatever the price needs to be
         
      if (!SendAlertNotTrade)
      {
         
         stop = CalculateStopLoss(OP_SELL, price);
         
         
         take = CalculateTakeProfit(OP_SELL, price);
         
         
         //Lot size calculated by risk
         if (RiskPercent > 0) SendLots = CalculateLotSize(price, NormalizeDouble(stop - (HiddenPips / factor), Digits) );

         type = OP_SELL;
         
         if (!SendAlertNotTrade) 
         { 
            result = SendSingleTrade(Symbol(), type, TradeComment, SendLots, price, stop, take);
            if (result) 
            {
               ObjectDelete(0, sellline);
               if (EmailTradeNotification) SendMail("Trade sent ", Symbol() + stype + "trade at " + TimeToStr(TimeCurrent(), TIME_DATE|TIME_MINUTES));
               if (AlertPush) AlertNow(WindowExpertName() + " " + Symbol() + " " + stype + " " + DoubleToStr(price, Digits) );
               OrderSelect(TicketNo, SELECT_BY_TICKET, MODE_TRADES);
               CheckTpSlAreCorrect(type);
            }//if (result)          
         }//if (!SendAlertNotTrade) 
         
         if (SendAlertNotTrade && !AlertSent)
         {
            Alert(WindowExpertName(), " ", Symbol(), " ", stype, "trade has triggered. ",  TimeToStr(TimeLocal(), TIME_DATE|TIME_MINUTES|TIME_SECONDS) );
            SendMail("Trade alert. ", Symbol() + " " + stype + " trade has triggered. " +  TimeToStr(TimeLocal(), TIME_DATE|TIME_MINUTES|TIME_SECONDS ));
            if (AlertPush) AlertNow(WindowExpertName() + " " + Symbol() + " " + stype + " " + DoubleToStr(price, Digits) );         
            AlertSent=true;
          }//if (SendAlertNotTrade && !AlertSent)
      }//if (!SendAlertNotTrade)

      //Actions when trade send succeeds
      if (result)
      {      
         if (!SendAlertNotTrade && !CloseEnough(HiddenPips, 0) ) ReplaceMissingSlTpLines();
      }//if (result)
      
      //Actions when trade send fails
      if (!result)
      {
         OldBarsTime = 0;
      }//if (!result)
      
   }//if (Bid <= target)
   

}//End void HasSellFilled


void AlertNow(string sAlertMsg) 
{
  
  if (AlertPush) 
  {
    if ( IsTesting() ) Print("Message to Push: ", TimeToStr(Time[0],TIME_DATE|TIME_SECONDS )+" "+sAlertMsg );
    SendNotification( StringConcatenate(TimeToStr(Time[0],TIME_DATE|TIME_SECONDS )," "+sAlertMsg));
  }//if (AlertPush) 
  return;
}//End void AlertNow(string sAlertMsg) 

bool CloseTrade(int ticket)
{   
   while(IsTradeContextBusy()) Sleep(100);
   bool orderselect=OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES);
   if (!orderselect) return(false);

   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)
   {
      ReportError(" CloseTrade()", ocm);
      return(false);
   }//if (!result)
   
   return(0);
}//End bool CloseTrade(ticket)

////////////////////////////////////////////////////////////////////////////////////////
//Indicator module

void CheckForSpreadWidening()
{
   if (CloseEnough(AverageSpread, 0)) return;
   //Detect a dramatic widening of the spread and pause the ea until this passes
   double TargetSpread = AverageSpread * MultiplierToDetectStopHunt;
   double spread = (Ask - Bid) * factor;
   
   if (spread >= TargetSpread)
   {
      if (OpenTrades == 0) Comment(Gap + "PAUSED DURING A MASSIVE SPREAD EVENT");
      if (OpenTrades > 0) Comment(Gap + "PAUSED DURING A MASSIVE SPREAD EVENT. STILL MONITORING TRADES.");
      while (spread >= TargetSpread)
      {
         RefreshRates();
         spread = (Ask - Bid) * factor;
         
         CountOpenTrades();
         //Safety feature. Sometimes an unexpected concatenation of inputs choice and logic error can cause rapid opening-closing of trades. Detect a closed trade and check that is was not a rogue.
         if (OldOpenTrades != OpenTrades)
         {
            if (IsClosedTradeRogue() )
            {
               RobotSuspended = true;
               return;
            }//if (IsClosedTradeRogue() )      
         }//if (OldOpenTrades != OpenTrades)
         if (ForceTradeClosure) return;//Emergency measure to force a retry at the next tick
         
         OldOpenTrades = OpenTrades;
         
         Sleep(1000);

      }//while (spread >= TargetSpread)      
   }//if (spread >= TargetSpread)
}//End void CheckForSpreadWidening()

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()

//+------------------------------------------------------------------+
//| GetSlope()                                                       |
//+------------------------------------------------------------------+
double GetSlope(string symbol, int tf, int shift)
{
 double atr = iATR(symbol, tf, 100, shift + 10) / 10;
 double gadblSlope = 0.0;
 if ( atr != 0 )
 {
    double dblTma = calcTma( symbol, tf, shift );
    double dblPrev = calcTma( symbol, tf, shift + 1 );
    gadblSlope = ( dblTma - dblPrev ) / atr;
 }
 
 return ( gadblSlope );

}

//+------------------------------------------------------------------+
//| calcTma()                                                        |
//+------------------------------------------------------------------+
double calcTma( string symbol, int tf,  int shift )
{
 double dblSum  = iClose(symbol, tf, shift) * 21;
 double dblSumw = 21;
 int jnx, knx;
       
 for ( jnx = 1, knx = 20; jnx <= 20; jnx++, knx-- )
 {
    dblSum  += ( knx * iClose(symbol, tf, shift + jnx) );
    dblSumw += knx;

    if ( jnx <= shift )
    {
       dblSum  += ( knx * iClose(symbol, tf, shift - jnx) );
       dblSumw += knx;
    }
 }
 
 return( dblSum / dblSumw );

}


void GetAverageSpread()
{
 
   static double SpreadTotal = 0;
   AverageSpread = 0;
   
   //Add spread to total and keep track of the ticks
   double Spread = (Ask - Bid) * factor;
   SpreadTotal+= Spread;
   CountedTicks++;
   
   //All ticks counted?
   if (CountedTicks >= TicksToCount)
   {
      AverageSpread = NormalizeDouble(SpreadTotal / TicksToCount, 1);
      //Save the average for restarts.
      GlobalVariableSet(SpreadGvName, AverageSpread);
      RunInSpreadDetectionMode = false;
   }//if (CountedTicks >= TicksToCount)
   
   
   
}//void GetAverageSpread()

double GetMa(string symbol, int tf, int period, int mashift, int method, int ap, int shift)
{
   return(iMA(symbol, tf, period, mashift, method, ap, shift) );
}//End double GetMa(int tf, int period, int mashift, int method, int ap, int shift)

void SplitSymbol()
{
   Curr1 = StringSubstrOld(Symbol(), 0, 3);
   Curr2 = StringSubstrOld(Symbol(), 3, 3);
   
   //Calculate the index to pass to CSS
   int cc;
   for (cc = 0; cc < ArraySize(CurrNames); cc++)
   {
      if (Curr1 == CurrNames[cc])
      {
         CurrIndex1 = cc;
         break;
      }//if (Curr1 == CurrNames[cc])
   }//for (cc = 0; cc < ArraySize(CurrNames); cc++)
   
   for (cc = 0; cc < ArraySize(CurrNames); cc++)
   {
      if (Curr2 == CurrNames[cc])
      {
         CurrIndex2 = cc;
         break;
      }//if (Curr1 == CurrNames[cc])
   }//for (cc = 0; cc < ArraySize(CurrNames); cc++)

}//End void SplitSymbol()

double GetCSS(double index, int shift)
{

   // return(iCustom(NULL, 0, "10.5 CSS 4H 1.0.8 modified for automation", autoSymbols, symbolsToWeigh, maxBars, addSundayToMonday, timeFrame, ignoreFuture, index, shift));
   
   // Initialize
   double myCSS[];
   // Call libary
   // Do not care about multiple calls, libCCS caches its values internally
   libCSSgetCSS( myCSS, CssTf, shift, true );
   
   int currencyIndex = NormalizeDouble( index, 0 );
   
   return ( myCSS[currencyIndex] );

}//End double GetCSS(int index, int shift)

//~ int GetTimeFrame()
//~ {

   //~ //Converts CSS timeFrame input into an integer
   //~ if (timeFrame == "M1") return(PERIOD_M1);
   //~ if (timeFrame == "M5") return(PERIOD_M5);
   //~ if (timeFrame == "M15") return(PERIOD_M15);
   //~ if (timeFrame == "M30") return(PERIOD_M30);
   //~ if (timeFrame == "H1") return(PERIOD_H1);
   //~ if (timeFrame == "H4") return(PERIOD_H4);
   //~ if (timeFrame == "D1") return(PERIOD_D1);
   //~ if (timeFrame == "W1") return(PERIOD_W1);
   //~ if (timeFrame == "MN") return(PERIOD_MN1);
   
   //~ //Got this far, so return the current tf
   //~ return(Period());

//~ }//End int GetTimeFrame()

double GetRsiTma(int shift)
{

   // Call LibCSS
   return ( libCSSgetSlopeRSI( Symbol(), TmaRsi2TF, shift ) ); 

}//double GetRsiTma()

void GetPreviousCandlesColour()
{
   Tf1Colour = none;
   if (iClose(Symbol(), TF1, 1) >  iOpen(Symbol(), TF1, 1))
      Tf1Colour = green;
   else
      if (iClose(Symbol(), TF1, 1) <  iOpen(Symbol(), TF1, 1))
         Tf1Colour = red;
   
   datetime time = iTime(Symbol(), TF1, 1);
   int shift = iBarShift(Symbol(), TF2, time, false);
   shift+= 1;
     
   Tf2Colour = none;
   if (iClose(Symbol(), TF2, shift) >  iOpen(Symbol(), TF2, shift))
      Tf2Colour = green;
   else
      if (iClose(Symbol(), TF2, shift) <  iOpen(Symbol(), TF2, shift))
         Tf2Colour = red;
         
   shift = iBarShift(Symbol(), TF3, time, false);     
   shift+= 1;
   Tf3Colour = none;
   if (iClose(Symbol(), TF3, shift) >  iOpen(Symbol(), TF3, shift))
      Tf3Colour = green;
   else
      if (iClose(Symbol(), TF3, shift) <  iOpen(Symbol(), TF3, shift))
         Tf3Colour = red;
         
   shift = iBarShift(Symbol(), TF4, time, false);
   shift+= 1;
   Tf4Colour = none;
   if (iClose(Symbol(), TF4, shift) >  iOpen(Symbol(), TF4, shift))
      Tf4Colour = green;
   else
      if (iClose(Symbol(), TF4, shift) <  iOpen(Symbol(), TF4, shift))
         Tf4Colour = red;
         
      
}//void GetPreviousCandlesColour()

void ReadIndicatorValues()
{

   int cc;
   
   //Set up the candle colour variables
   GetPreviousCandlesColour();
   //Create tp/sl for displaying the values that would have been used had there been a trade
   if (StopLossPips == 0)
   {
      if (Tf1Colour == green)
      {
         StopLoss = (iClose(Symbol(), TF1, 1) - iLow(Symbol(), TF1, 1)) * factor;
         StopLoss-= StopLossBuffer;
      }//if (Tf1Colour == green)
      else
         if (Tf1Colour == red)
         {
            StopLoss = (iHigh(Symbol(), TF1, 1) - iClose(Symbol(), TF1, 1)) * factor;
            StopLoss-= StopLossBuffer;
         }//if (Tf1Colour == green)         
   }//if (StopLossPips == 0)
   if(TakeProfitPips == 0)
      TakeProfit = StopLoss * TakeProfitMultiplier;
   
   //RSI TMA Slope
   if (UseTmaRsi2)
   {
      static datetime OldRSTBartime;
      static datetime OldPRSTBartime;
      if (OldRSTBartime != iTime(NULL, PERIOD_M1, 0) )
      {
         RsiPinStatus = pinnone;
         //MA
         OldRSTBartime = iTime(NULL, PERIOD_M1, 0);
         RsiTmaVal[0] = GetRsiTma(0);//Current value
         if (RsiTmaVal[0] >= PinHighLevel) RsiPinStatus = pinhigh;
         if (RsiTmaVal[0] <= PinLowLevel) RsiPinStatus = pinlow;
         
         //Close of previous candles
         if (OldPRSTBartime != Time[0])
         {
            OldPRSTBartime = Time[0];
            for (cc = 1; cc<= 3; cc++)
            {
               RsiTmaVal[cc] = GetRsiTma(cc);
               if (RsiTmaVal[cc] >= PinHighLevel) RsiPinStatus = pinhigh;
               if (RsiTmaVal[cc] <= PinLowLevel) RsiPinStatus = pinlow;
            }//for (cc = 1; cc>= 3; cc++)         
         }//if (OldPRSTBartime != Time[0])      
      }//if (OldRSTBartime != iTime(NULL, PERIOD_M1, 0) )
   }//if (UseTmaRsi2)
   
   
   //CCS
   if (UseCSS)
   {
      static datetime OldCssBarsTime, OldShiftedBarTime;
      int TimeFrame = 1;
      if (EveryTickMode) 
      {

      }//if (EveryTickMode) 
      
      int shift=0;
      if (!EveryTickMode) 
      {
         shift = 1;
         TimeFrame = CssTf;
      }//if (!EveryTickMode) 
      
      if (OldCssBarsTime != iTime(NULL, TimeFrame, 0) )
      {
         OldCssBarsTime = iTime(NULL, TimeFrame, 0);
         SplitSymbol();//Split the Symbol into its constituent currencies. Also finds their index for passing to CSS
         CurrVal1[1] = GetCSS(CurrIndex1, shift);
         CurrVal2[1] = GetCSS(CurrIndex2, shift);
         if (OldShiftedBarTime != iTime(NULL, TimeFrame, shift + 1) )
         {
            OldShiftedBarTime = iTime(NULL, TimeFrame, shift + 1);
            CurrVal1[2] = GetCSS(CurrIndex1, shift + 1);
            CurrVal2[2] = GetCSS(CurrIndex2, shift + 1);         
         }//if (OldShiftedBarTime != iTime(NULL, TimeFrame, shift + 1) )         
      
         //Define direction
         //Currency 1
         if (CurrVal1[1] > 0 && CurrVal1[1] > CurrVal1[2])  CurrDirection1 = upaccelerating;
         if (CurrVal1[1] > 0 && CurrVal1[1] <= CurrVal1[2])  CurrDirection1 = updecelerating;
         
         if (CurrVal1[1] < 0 && CurrVal1[1] < CurrVal1[2])  CurrDirection1 = downaccelerating;
         if (CurrVal1[1] < 0 && CurrVal1[1] >= CurrVal1[2])  CurrDirection1 = downdecelerating;
         
         //Currency 2
         if (CurrVal2[1] > 0 && CurrVal2[1] > CurrVal2[2])  CurrDirection2 = upaccelerating;
         if (CurrVal2[1] > 0 && CurrVal2[1] <= CurrVal2[2])  CurrDirection2 = updecelerating;
         
         if (CurrVal2[1] < 0 && CurrVal2[1] < CurrVal2[2])  CurrDirection2 = downaccelerating;
         if (CurrVal2[1] < 0 && CurrVal2[1] >= CurrVal2[2])  CurrDirection2 = downdecelerating;
      
      }//if (OldCssBarsTime != iTime(NULL, PERIOD_M1, 0) )
      
      
   }//if (UseCSS)

   //MA
   if (MaPeriod > 0)
   {
      static datetime OldM1BarTime;
      if (OldM1BarTime != iTime(NULL, PERIOD_M1, 0) && MaPeriod > 0)
      {
         OldM1BarTime = iTime(NULL, PERIOD_M1, 0);
         //~ TradeLong = false;
         //~ TradeShort = false;
         MaVal = GetMa(Symbol(), MaTF, MaPeriod, MaShift, MaMethod, MaAppliedPrice, 0);
         if (Bid > MaVal) 
         {
            MaTrend = up;
         }//if (Bid > MaVal) 
         
         if (Bid < MaVal) 
         {
            MaTrend = down;
         }//if (Bid < MaVal) 

      }//if (OldM1BarTime != iTime(NULL, PERIOD_M1, 0))
   }//if (MaPeriod > 0)
   


   //Slope.
   //Delete whichever lines are not required by the program you are coding.
   static datetime OldHtfBarTime;
   static datetime OldLtfBarTime;
   
   if (HtfTimeFrame > 0)
   {
      HtfSlopeVal = GetSlope(Symbol(), HtfTimeFrame, 0);
      HtfSlopeTrend = ranging;
      if (HtfSlopeVal >= HtfBuyOnlyLevel) HtfSlopeTrend = buyonly;
      if (HtfSlopeVal >= HtfBuyHoldLevel) HtfSlopeTrend = buyhold;
      if (HtfSlopeVal <= HtfSellOnlyLevel) HtfSlopeTrend = sellonly;
      if (HtfSlopeVal <= HtfSellHoldLevel) HtfSlopeTrend = sellhold;
   
      if (OldHtfBarTime != iTime(NULL, HtfTimeFrame, 0) )
      {
         PrevHtfSlopeVal = GetSlope(Symbol(), HtfTimeFrame, 1);
         OldHtfBarTime = iTime(NULL, HtfTimeFrame, 0);
      }//if (OldBarTime != iTime(NULL, HtfTimeFrame, 0)
      
      
      HtfSlopeAngle = unchanged;
      if (HtfSlopeVal > PrevHtfSlopeVal) HtfSlopeAngle = rising;
      if (HtfSlopeVal < PrevHtfSlopeVal) HtfSlopeAngle = falling;      
   }//IF (HtfTimeFrame > 0)

   if (LtfTimeFrame > 0)
   {
      LtfSlopeVal = GetSlope(Symbol(), LtfTimeFrame, 0);
      LtfSlopeTrend = ranging;
      if (LtfSlopeVal >= LtfBuyOnlyLevel) LtfSlopeTrend = buyonly;
      if (LtfSlopeVal >= LtfBuyHoldLevel) LtfSlopeTrend = buyhold;
      if (LtfSlopeVal <= LtfSellOnlyLevel) LtfSlopeTrend = sellonly;
      if (LtfSlopeVal <= LtfSellHoldLevel) LtfSlopeTrend = sellhold;
   
      if (OldLtfBarTime != iTime(NULL, LtfTimeFrame, 0) )
      {
         PrevLtfSlopeVal = GetSlope(Symbol(), LtfTimeFrame, 1);
         OldLtfBarTime = iTime(NULL, LtfTimeFrame, 0);
      }//if (OldBarTime != iTime(NULL, HtfTimeFrame, 0)
         
      LtfSlopeAngle = unchanged;
      if (LtfSlopeVal > PrevLtfSlopeVal) LtfSlopeAngle = rising;
      if (LtfSlopeVal < PrevLtfSlopeVal) LtfSlopeAngle = falling;      
   }//if (LtfTimeFrame > 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 = false;
   
   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);
   if (CloseEnough(take, 0) ) take = OrderTakeProfit();
   LineName = SlPrefix + DoubleToStr(ticket, 0);
   double stop = ObjectGet(LineName, OBJPROP_PRICE1);
   if (CloseEnough(stop, 0) ) stop = OrderStopLoss();
   
   
   if (OrderType() == OP_BUY)
   {
      //TP
      if (Bid >= take && !CloseEnough(take, 0) && !CloseEnough(take, OrderTakeProfit()) ) CloseThisTrade = true;
      //SL
      if (Bid <= stop && !CloseEnough(stop, 0)  && !CloseEnough(stop, OrderStopLoss())) CloseThisTrade = true;

      //Slope closures
      if (HtfTimeFrame > 0)
      {
         if (HtfSlopeVal <= HtfBuyCloseLevel)  CloseThisTrade = true;            
      }//if (HtfTimeFrame > 0)
      
      if (LtfTimeFrame > 0)
      {
         if (LtfSlopeVal <= LtfBuyCloseLevel)  CloseThisTrade = true;            
      }//if (LtfTimeFrame > 0)

   }//if (OrderType() == OP_BUY)
   
   
   if (OrderType() == OP_SELL)
   {
      //TP
      if (Bid <= take && !CloseEnough(take, 0) && !CloseEnough(take, OrderTakeProfit()) ) CloseThisTrade = true;
      //SL
      if (Bid >= stop && !CloseEnough(stop, 0)  && !CloseEnough(stop, OrderStopLoss())) CloseThisTrade = true;



      //Slope closures
      if (HtfTimeFrame > 0)
      {
         if (HtfSlopeVal >= HtfSellCloseLevel)  CloseThisTrade = true;            
      }//if (HtfTimeFrame > 0)
      
      if (LtfTimeFrame > 0)
      {
         if (LtfSlopeVal >= LtfSellCloseLevel)  CloseThisTrade = true;            
      }//if (LtfTimeFrame > 0)

   }//if (OrderType() == OP_SELL)
   
   if (CloseThisTrade)
   {
         bool result = CloseTrade(ticket);
      //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() 
{

	// Trade 24 hours if no input is given
	if ( ArraySize( tradeHours ) == 0 ) return ( true );

	// Get local time in minutes from midnight
    int time = TimeHour( TimeLocal() ) * 60 + TimeMinute( TimeLocal() );
   
	// Don't you love this?
	int i = 0;
	while ( time >= tradeHours[i] ) 
	{	
		if ( i == ArraySize( tradeHours ) ) break;
		i++;		
	}
	if ( i % 2 == 1 ) return ( true );
	return ( false );
}//End bool CheckTradingTimes2() 
//+------------------------------------------------------------------+
//| Initialize Trading Hours Array                                   |
//+------------------------------------------------------------------+
bool initTradingHours() 
{
   // Called from init()
   
	// Assume 24 trading if no input found
	if ( tradingHours == "" )	
	{
		ArrayResize( tradeHours, 0 );
		return ( true );
	}

	int i;

	// Add 00:00 start time if first element is stop time
	if ( StringSubstrOld( tradingHours, 0, 1 ) == "-" ) 
	{
		tradingHours = StringConcatenate( "+0,", tradingHours );   
	}
	
	// Add delimiter
	if ( StringSubstrOld( tradingHours, StringLen( tradingHours ) - 1) != "," ) 
	{
		tradingHours = StringConcatenate( tradingHours, "," );   
	}
	
	string lastPrefix = "-";
	i = StringFind( tradingHours, "," );
	
	while (i != -1) {

		// Resize array
		int size = ArraySize( tradeHours );
		ArrayResize( tradeHours, size + 1 );

		// Get part to process
		string part = StringSubstrOld( tradingHours, 0, i );

		// Check start or stop prefix
		string prefix = StringSubstrOld ( part, 0, 1 );
		if ( prefix != "+" && prefix != "-" ) 
		{
			Print("ERROR IN TRADINGHOURS INPUT (NO START OR CLOSE FOUND), ASSUME 24HOUR TRADING.");
			ArrayResize ( tradeHours, 0 );
			return ( true );
		}

		if ( ( prefix == "+" && lastPrefix == "+" ) || ( prefix == "-" && lastPrefix == "-" ) )	
		{
			Print("ERROR IN TRADINGHOURS INPUT (START OR CLOSE IN WRONG ORDER), ASSUME 24HOUR TRADING.");
			ArrayResize ( tradeHours, 0 );
			return ( true );
		}
		
		lastPrefix = prefix;

		// Convert to time in minutes
		part = StringSubstrOld( part, 1 );
		double time = StrToDouble( part );
		int hour = MathFloor( time );
		int minutes = MathRound( ( time - hour ) * 100 );

		// Add to array
		tradeHours[size] = 60 * hour + minutes;

		// Trim input string
		tradingHours = StringSubstrOld( tradingHours, i + 1 );
		i = StringFind( tradingHours, "," );
	}

	return ( true );
}//End bool initTradingHours() 


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
   TradeHasPartClosed=false;
   
   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, MODE_TRADES) ) continue;
      //Ensure the EA 'owns' this trade
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderMagicNumber() != MagicNumber) continue;
      if (OrderCloseTime() > 0) 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()
      
      //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 (CloseEnough(OrderStopLoss(), 0) && !CloseEnough(StopLoss, 0)) InsertStopLoss(OrderTicket());
      if (CloseEnough(OrderTakeProfit(), 0) && !CloseEnough(TakeProfit, 0)) InsertTakeProfit(OrderTicket() );

      //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++;
         continue;
      }//if (TradeWasClosed) 
         
      //Profitable trade management
      if (OrderProfit() > 0) 
      {
         TradeManagementModule();
         if (TradeHasPartClosed) continue;//Part-closing changes the ticket number, so we cannot continue the current loop iteration
      }//if (OrderProfit() > 0) 
            
      //Trade types and half-close, and adjust sl/tp in case slippage has caused them to be inaccurate when the trade was sent.
      if (OrderType() == OP_BUY) 
      {
         BuyOpen = true;
         if (PartCloseEnabled && OrderComment() == TradeComment && OrderStopLoss() >= OrderOpenPrice() ) PartCloseTrade(OrderTicket() );
      }//if (OrderType() == OP_BUY) 
      
      if (OrderType() == OP_SELL) 
      {
         SellOpen = true;
         if (PartCloseEnabled && OrderComment() == TradeComment && OrderStopLoss() <= OrderOpenPrice()  && !CloseEnough(OrderStopLoss(), 0)) PartCloseTrade(OrderTicket() );
      }//if (OrderType() == OP_SELL) 
      
   }//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.
   
   if (!OrderSelect(ticket, SELECT_BY_TICKET)) return;
   if (OrderCloseTime() > 0) return;//Somehow, we are examining a closed trade
   if (OrderStopLoss() > 0) return;//Function called unnecessarily.
   
   while(IsTradeContextBusy()) Sleep(100);
   
   double stop;
   
   if (OrderType() == OP_BUY)
   {
      stop = CalculateStopLoss(OP_BUY, OrderOpenPrice());
   }//if (OrderType() == OP_BUY)
   
   if (OrderType() == OP_SELL)
   {
      stop = CalculateStopLoss(OP_SELL, OrderOpenPrice());
   }//if (OrderType() == OP_SELL)
   
   if (CloseEnough(stop, 0) ) return;
   
   //In case some errant behaviour/code creates a sl the wrong side of the market, which would cause an instant close.
   if (OrderType() == OP_BUY && stop > OrderOpenPrice() ) 
   {
      stop = 0;
      ReportError(" InsertStopLoss()", " stop loss > market ");
   }//if (OrderType() == OP_BUY && take < OrderOpenPrice() ) 
   
   if (OrderType() == OP_SELL && stop < OrderOpenPrice() ) 
   {
      stop = 0;
      ReportError(" InsertStopLoss()", " stop loss > market ");
   }//if (OrderType() == OP_SELL && take > OrderOpenPrice() ) 

   
   if (!CloseEnough(stop, OrderStopLoss())) 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.
   
   if (!OrderSelect(ticket, SELECT_BY_TICKET)) return;
   if (OrderCloseTime() > 0) return;//Somehow, we are examining a closed trade
   if (!CloseEnough(OrderTakeProfit(), 0) ) return;//Function called unnecessarily.
   
   while(IsTradeContextBusy()) Sleep(100);
   
   double take;
   
   if (OrderType() == OP_BUY)
   {
      take = CalculateTakeProfit(OP_BUY, OrderOpenPrice());
   }//if (OrderType() == OP_BUY)
   
   if (OrderType() == OP_SELL)
   {
      take = CalculateTakeProfit(OP_SELL, OrderOpenPrice());
   }//if (OrderType() == OP_SELL)
   
   if (CloseEnough(take, 0) ) return;
   
   //In case some errant behaviour/code creates a tp the wrong side of the market, which would cause an instant close.
   if (OrderType() == OP_BUY && take < OrderOpenPrice()  && !CloseEnough(take, 0) ) 
   {
      take = 0;
      ReportError(" InsertTakeProfit()", " take profit < market ");
      return;
   }//if (OrderType() == OP_BUY && take < OrderOpenPrice() ) 
   
   if (OrderType() == OP_SELL && take > OrderOpenPrice() ) 
   {
      take = 0;
      ReportError(" InsertTakeProfit()", " take profit < market ");
      return;
   }//if (OrderType() == OP_SELL && take > OrderOpenPrice() ) 
   
   
   if (!CloseEnough(take, OrderTakeProfit())) OrderModify(ticket, OrderOpenPrice(), OrderStopLoss(), take, OrderExpiration(), CLR_NONE);

}//End void InsertTakeProfit(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 / factor), Digits);
      }//if (OrderType() == OP_BUY)
      
      if (OrderType() == OP_SELL)
      {
         HiddenTakeProfit = NormalizeDouble(OrderTakeProfit() + (HiddenPips / factor), 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 || OrderType() == OP_BUYSTOP || OrderType() == OP_BUYLIMIT)
      {
         HiddenStopLoss = NormalizeDouble(OrderStopLoss() + (HiddenPips / factor), Digits);
      }//if (OrderType() == OP_BUY)
      
      if (OrderType() == OP_SELL || OrderType() == OP_SELLSTOP || OrderType() == OP_SELLLIMIT)
      {
         HiddenStopLoss = NormalizeDouble(OrderStopLoss() - (HiddenPips / factor), 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 ((StringSubstrOld(name, 0, 2) == TpPrefix || StringSubstrOld(name, 0, 2) == SlPrefix) && ObjectType(name) == OBJ_HLINE)
      {
         int tn = StrToDouble(StringSubstrOld(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 (StringSubstrOld(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(string function, string message)
{
   //All purpose sl mod error reporter. Called when a sl mod fails
   
   int err=GetLastError();
   if (err == 1) return;//That bloody 'error but no error' report is a nuisance
   
      
   Alert(WindowExpertName(), " ", OrderTicket(), function, message, err,": ",ErrorDescription(err));
   Print(WindowExpertName(), " ", OrderTicket(), function, message, 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);
   double target = OrderOpenPrice();
   
   if (OrderType()==OP_BUY)
   {
      if (HiddenPips > 0) target-= (HiddenPips / factor);
      if (OrderStopLoss() >= target) return;
      if (Bid >= OrderOpenPrice () + (BreakEvenPips / factor))          
      {
         //Calculate the new stop
         NewStop = NormalizeDouble(OrderOpenPrice()+(BreakEvenProfit / factor), 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 (HiddenPips > 0) target+= (HiddenPips / factor);
      if (OrderStopLoss() <= target && OrderStopLoss() > 0) return;
     if (Ask <= OrderOpenPrice() - (BreakEvenPips / factor)) 
     {
         //Calculate the new stop
         NewStop = NormalizeDouble(OrderOpenPrice()-(BreakEvenProfit / factor), 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(" BreakEvenStopLoss()", slm);
      
      while (IsTradeContextBusy() ) Sleep(100);
      if (PartCloseEnabled && OrderComment() == TradeComment) bool success = PartCloseTrade(OrderTicket() );
   }//if (modify)
   
} // End BreakevenStopLoss sub

bool PartCloseTrade(int ticket)
{
   //Close PartClosePercent of the initial trade.
   //Return true if close succeeds, else false
   if (!OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)) return(true);//in case the trade closed
   
   bool Success = false;
   double CloseLots = NormalizeLots(OrderSymbol(),OrderLots() * (PartClosePercent / 100));
   
   Success = OrderClose(ticket, CloseLots, OrderClosePrice(), 1000, Blue); //fxdaytrader, NormalizeLots(...
   if (Success) TradeHasPartClosed = true;//Warns CountOpenTrades() that the OrderTicket() is incorrect.
   if (!Success) 
   {
       //mod. fxdaytrader, orderclose-retry if failed with ordercloseprice(). Maybe very seldom, but it can happen, so it does not hurt to implement this:
       while(IsTradeContextBusy()) Sleep(100);
       RefreshRates();
       if (OrderType()==OP_BUY) Success = OrderClose(ticket, CloseLots, MarketInfo(OrderSymbol(),MODE_BID), 5000, Blue);
       if (OrderType()==OP_SELL) Success = OrderClose(ticket, CloseLots, MarketInfo(OrderSymbol(),MODE_ASK), 5000, Blue);
       //end mod.  
       //original:
       if (Success) TradeHasPartClosed = true;//Warns CountOpenTrades() that the OrderTicket() is incorrect.
   
       if (!Success) 
       {
         ReportError(" PartCloseTrade()", pcm);
         return (false);
       } 
   }//if (!Success) 
      
   //Got this far, so closure succeeded
   return (true);   

}//bool PartCloseTrade(int ticket)

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 (CloseEnough(sl, 0) ) sl = OrderStopLoss();
   
   //if (CloseEnough(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) / factor) )
       if (CloseEnough(sl, 0) ) sl = MathMax(OrderStopLoss(), OrderOpenPrice());
       if (Bid >=  sl + ((JumpingStopPips * 2) / factor) )//George{
       {
          NewStop = NormalizeDouble(sl + (JumpingStopPips / factor), Digits);
          if (AddBEP) NewStop = NormalizeDouble(NewStop + (BreakEvenProfit / factor), 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 / factor) && 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) / factor)) Original code
          if (CloseEnough(sl, 0) ) sl = MathMin(OrderStopLoss(), OrderOpenPrice());
          if (CloseEnough(sl, 0) ) sl = OrderOpenPrice();
          if (Bid <= sl - ((JumpingStopPips * 2) / factor) )//George
          {
             NewStop = NormalizeDouble(sl - (JumpingStopPips / factor), Digits);
             if (AddBEP) NewStop = NormalizeDouble(NewStop - (BreakEvenProfit / factor), 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 / factor) && 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(" JumpingStopLoss()", slm);      
   }//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 (CloseEnough(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 / factor) ) Original code
          if (CloseEnough(sl, 0) ) sl = MathMax(OrderStopLoss(), OrderOpenPrice());
          if (Bid >= sl + (TrailingStopPips / factor) )//George
          {
             NewStop = NormalizeDouble(sl + (TrailingStopPips / factor), 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 / factor) )//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 / factor) ) Original code
          if (CloseEnough(sl, 0) ) sl = MathMin(OrderStopLoss(), OrderOpenPrice());
          if (CloseEnough(sl, 0) ) sl = OrderOpenPrice();
          if (Bid <= sl  - (TrailingStopPips / factor))//George
          {
             NewStop = NormalizeDouble(sl - (TrailingStopPips / factor), 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 / factor) )//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(" TrailingStopLoss()", slm);
   }//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 (CloseEnough(sl, 0) ) sl = OrderStopLoss();
   double NewStop;
   bool modify=false;
   bool result;
   

   if (OrderType() == OP_BUY)
   {
      if (iLow(NULL, CstTimeFrame, CstTrailCandles) > sl)
      {
         NewStop = NormalizeDouble(iLow(NULL, CstTimeFrame, CstTrailCandles), Digits);
         //Check that the new stop is > the old. Exit the function if not.
         if (NewStop < OrderStopLoss() || CloseEnough(NewStop, OrderStopLoss()) ) return;
         //Check that the new stop locks in profit, if the user requires this.
         if (TrailMustLockInProfit && NewStop < OrderOpenPrice() ) return;
         
         if (HiddenPips > 0) 
         {
            ObjectMove(LineName, 0, Time[0], NewStop);
            NewStop = NormalizeDouble(NewStop - (HiddenPips / factor), 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);
         
         //Check that the new stop is < the old. Exit the function if not.
         if (NewStop > OrderStopLoss() || CloseEnough(NewStop, OrderStopLoss()) ) return;
         //Check that the new stop locks in profit, if the user requires this.
         if (TrailMustLockInProfit && NewStop > OrderOpenPrice() ) return;
         
         if (HiddenPips > 0) 
         {
            ObjectMove(LineName, 0, Time[0], NewStop);
            NewStop = NormalizeDouble(NewStop + (HiddenPips / factor), 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(" CandlestickTrailingStop()", slm);
      if (!result) 
      {
         ReportError(" CandlestickTrailingStop()", slm);
         OldCstBars = 0;
      }//if (!result) 
      
   }//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(int type)
{
   //This code supplied by Lifesys. Many thanks Paul.
   
   //Returns the pips Upl of the currently selected trade. Called by CountOpenTrades()
   double profit;
   // double point = BrokerPoint(OrderSymbol() ); // no real use
   double ask = MarketInfo(OrderSymbol(), MODE_ASK);
   double bid = MarketInfo(OrderSymbol(), MODE_BID);

   if (type == OP_BUY)
   {
      profit = bid - OrderOpenPrice();
   }//if (OrderType() == OP_BUY)

   if (type == OP_SELL)
   {
      profit = OrderOpenPrice() - ask;
   }//if (OrderType() == OP_SELL)
   //profit *= PFactor(OrderSymbol()); // use PFactor instead of point. This line for multi-pair ea's
   profit *= factor; // use PFactor instead of point.

   return(profit); // in real pips
}//double CalculateTradeProfitInPips(int type)

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 (num1 == 0 && num2 == 0) return(true); //0==0
   if (MathAbs(num1 - num2) / (MathAbs(num1) + MathAbs(num2)) < 0.00000001) return(true);
   
   //Doubles are unequal
   return(false);

}//End bool CloseEnough(double num1, double num2)

double PFactor(string symbol)
{
   //This code supplied by Lifesys. Many thanks Paul - we all owe you. Gary was trying to make me see this, but I could not understand his explanation. Paul used Janet and John words
   
   for ( int i = ArraySize(pipFactor)-1; i >=0; i-- ) 
      if (StringFind(symbol,pipFactor[i],0) != -1) 
         return (pipFactors[i]);
   return(10000);

}//End double PFactor(string pair)


void GetSwap(string symbol)
{
   LongSwap = MarketInfo(symbol, MODE_SWAPLONG);
   ShortSwap = MarketInfo(symbol, MODE_SWAPSHORT);

}//End void GetSwap()

bool TooClose()
{
   //Returns false if the previously closed trade and the proposed new trade are sufficiently far apart, else return true. Called from IsTradeAllowed().
   
   SafetyViolation = false;//For chart feedback
         
   if (OrdersHistoryTotal() == 0) return(false);
   
   for (int cc = OrdersHistoryTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS, MODE_HISTORY) ) continue;
      if (OrderMagicNumber() != MagicNumber) continue;
      if (OrderSymbol() != Symbol() ) continue;
      
      //Examine the OrderCloseTime to see if it closed far enought back in time.
      if (TimeCurrent() - OrderCloseTime() < (MinMinutesBetweenTrades * 60))
      {
         SafetyViolation = true;
         return(true);//Too close, so disallow the trade
      }//if (OrderCloseTime() - TimeCurrent() < (MinMinutesBetweenTrades * 60))
      break;      
   }//for (int cc = OrdersHistoryTotal() - 1; cc >= 0; cc--)
   
   //Got this far, so there is no disqualifying trade in the history
   return(false);
   
}//bool TooClose()

bool IsClosedTradeRogue()
{
   //~ Safety feature. Sometimes an unexpected concatenation of inputs choice and logic error can cause rapid opening-closing of trades. Detect a closed trade and check that is was not a rogue. Examine trades closed within the last 5 minutes.
   
   //~ If it is a rogue:
   //~ * Show a warning alert.
   //~ * Send an email alert.
   //~ * Suspend the robot
   
   if (OrdersHistoryTotal() == 0) return(false);
   
   datetime latestTime = TimeCurrent() - ( 5 * 60 );
  
   datetime duration = -1; //impossible value
  
   //We cannot guarantee that the most recent trade shown in our History tab is actually the most recent on the crim's server - CraptT4 again. pah has supplied this code to ensure that we are examining the latest trade. Many thanks, Paul.
   
   // look for trades that closed within the last 5 minutes
   // otherwise we will always find the last rogue trade
   // even when that happened some time ago and can be ignored
   
   for ( int i = OrdersHistoryTotal()-1; i >= 0; i-- )
   {
      if ( ! OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) ) continue;
       
      if ( OrderMagicNumber() != MagicNumber || OrderSymbol() != Symbol() ) continue;
        
      if ( OrderCloseTime() >= latestTime )
      {
         latestTime = OrderCloseTime();
         duration    = OrderCloseTime() - OrderOpenTime();
      }//if ( OrderCloseTime() >= latestTime )
       
   }//for ( int i = OrdersHistoryTotal()-1; i >= 0; i-- )
   
  
   bool rogue = ( duration >= 0 ) && ( duration < ( MinMinutesBetweenTradeOpenClose * 60) );
  
   if (rogue)
   {
      RobotSuspended = true;
      Alert(Symbol(), " ", WindowExpertName() , " possible rogue trade.");
      SendMail("Possible rogue trade warning ", Symbol() + " " + WindowExpertName() + " possible rogue trade.");
      Comment(NL, Gap, "****************** ROBOT SUSPENDED. POSSIBLE ROGUE TRADING ACTIVITY. REMOVE THIS EA IMMEDIATELY ****************** ");
      return(true);//Too close, so disallow the trade
   
   }//if (rogue)
   
   //Got this far, so there is no rogue trade
   return(false);
   


}//bool IsClosedTradeRogue()

void DrawTrendLine(string name, datetime time1, double val1, datetime time2, double val2, color col, int width, int style, bool ray)
{
   //Plots a trendline with the given parameters
   
   ObjectDelete(name);
   
   ObjectCreate(name, OBJ_TREND, 0, time1, val1, time2, val2);
   ObjectSet(name, OBJPROP_COLOR, col);
   ObjectSet(name, OBJPROP_WIDTH, width);
   ObjectSet(name, OBJPROP_STYLE, style);
   ObjectSet(name, OBJPROP_RAY, ray);
   
}//End void DrawLine()

void DrawHorizontalLine(string name, double price, color col, int style, int width)
{
   
   ObjectDelete(name);
   
   ObjectCreate(name, OBJ_HLINE, 0, TimeCurrent(), price);
   ObjectSet(name, OBJPROP_COLOR, col);
   ObjectSet(name, OBJPROP_STYLE, style);
   ObjectSet(name, OBJPROP_WIDTH, width);
   

}//void DrawLine(string name, double price, color col)

void DrawVerticalLine(string name, color col, int style, int width)
{
      //ObjectCreate(vline,OBJ_VLINE,0,iTime(NULL, TimeFrame, 0), 0);
   ObjectDelete(name);
   ObjectCreate(name,OBJ_VLINE,0,iTime(NULL, 0, 0), 0);
   ObjectSet(name, OBJPROP_COLOR, col);
   ObjectSet(name, OBJPROP_STYLE, style);
   ObjectSet(name, OBJPROP_WIDTH, width);

}//void DrawVerticalLine()

bool MarginCheck()
{

   EnoughMargin = true;//For user display
   MarginMessage = "";
   if (UseScoobsMarginCheck && OpenTrades > 0)
   {
      if(AccountMargin() > (AccountFreeMargin()/100)) 
      {
         MarginMessage = "There is insufficient margin to allow trading. You might want to turn off the UseScoobsMarginCheck input.";
         return(false);
      }//if(AccountMargin() > (AccountFreeMargin()/100)) 
      
   }//if (UseScoobsMarginCheck)


   if (UseForexKiwi && AccountMargin() > 0)
   {
      
      double ml = NormalizeDouble(AccountEquity() / AccountMargin() * 100, 2);
      if (ml < FkMinimumMarginPercent)
      {
         MarginMessage = StringConcatenate("There is insufficient margin percent to allow trading. ", DoubleToStr(ml, 2), "%");
         return(false);
      }//if (ml < FkMinimumMarginPercent)
   }//if (UseForexKiwi && AccountMargin() > 0)
   
  
   //Got this far, so there is sufficient margin for trading
   return(true);
}//End bool MarginCheck()

string PeriodText(int per)
{

	switch (per)
	{
	case PERIOD_M1:
		return("M1");
	case PERIOD_M5:
		return("M5");
	case PERIOD_M15:
		return("M15");
	case PERIOD_M30:
		return("M30");
	case PERIOD_H1:
		return("H1");
	case PERIOD_H4:
		return("H4");
	case PERIOD_D1:
		return("D1");
	case PERIOD_MN1:
		return("MN1");
	default:
		return("");
	}

}//End string PeriodText(int per)


void CheckTpSlAreCorrect(int type)
{
   //Looks at an open trade and checks to see that the exact tp/sl were sent with the trade.
   
   
   double stop = 0, take = 0, diff = 0;
   bool ModifyStop = false, ModifyTake = false;
   bool result;
   
   //Is the stop at BE?
   if (type == OP_BUY && OrderStopLoss() >= OrderOpenPrice() ) return;
   if (type == OP_SELL && OrderStopLoss() <= OrderOpenPrice() ) return;
   
   if (type == OP_BUY)
   {
      if (!CloseEnough(OrderStopLoss(), 0) )
      {
         diff = (OrderOpenPrice() - OrderStopLoss()) * factor;
         if (!CloseEnough(diff, StopLoss + (HiddenPips / factor))) 
         {
            ModifyStop = true;
            stop = CalculateStopLoss(OP_BUY, OrderOpenPrice());
         }//if (!CloseEnough(diff, StopLoss) )          
      }//if (!CloseEnough(OrderStopLoss(), 0) )      

      if (!CloseEnough(OrderTakeProfit(), 0) )
      {
         diff = (OrderTakeProfit() - OrderOpenPrice()) * factor;
         if (!CloseEnough(diff, TakeProfit -  (HiddenPips / factor))) 
         {
            ModifyTake = true;
            take = CalculateTakeProfit(OP_BUY, OrderOpenPrice());
         }//if (!CloseEnough(diff, TakeProfit) )          
      }//if (!CloseEnough(OrderStopLoss(), 0) )      
   }//if (type == OP_BUY)
   
   if (type == OP_SELL)
   {
      if (!CloseEnough(OrderStopLoss(), 0) )
      {
         diff = (OrderStopLoss() - OrderOpenPrice() ) * factor;
         if (!CloseEnough(diff, StopLoss -  (HiddenPips / factor))) 
         {
            ModifyStop = true;
            stop = CalculateStopLoss(OP_SELL, OrderOpenPrice());

         }//if (!CloseEnough(diff, StopLoss) )          
      }//if (!CloseEnough(OrderStopLoss(), 0) )      

      if (!CloseEnough(OrderTakeProfit(), 0) )
      {
         diff = (OrderOpenPrice() - OrderTakeProfit() ) * factor;
         if (!CloseEnough(diff, TakeProfit +  (HiddenPips / factor))) 
         {
            ModifyTake = true;
            take = CalculateTakeProfit(OP_SELL, OrderOpenPrice());
         }//if (!CloseEnough(diff, TakeProfit) )          
      }//if (!CloseEnough(OrderStopLoss(), 0) )      
   }//if (type == OP_SELL)
   
   if (ModifyStop)
   {
      result = OrderModify(OrderTicket(), OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);
      if (!result) ReportError(" CheckTpSlAreCorrect()", slm);      
   }//if (ModifyStop)
   
   if (ModifyTake)
   {
      result = OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), take, OrderExpiration(), CLR_NONE);
      if (!result) ReportError(" CheckTpSlAreCorrect()", tpm);      
   }//if (ModifyStop)
   

}//void CheckTpSlAreCorrect(int type)

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//START OF PAUL'S (Baluda) Lib.CSS module
//Thank you, Paul, for providing the code and showing me how to use it. I am deeply grateful.
//Coders, go to http://www.stevehopwoodforex.com/phpBB3/viewtopic.php?f=45&t=2905 to read about implementing calls to the library. You might prefer the #include method, but you then have to atach the Lib.CSS to your post should you be coding an EA for wider release than just for your own use, and tell readers where it goes.

//+------------------------------------------------------------------+
//|                                                       LibCSS.mq4 |
//|                      Copyright 2013, Deltabron - Paul Geirnaerdt |
//|                                          http://www.deltabron.nl |
//+------------------------------------------------------------------+

#define libCSSversion            "v1.1.2"
#define libCSSEPSILON            0.00000001
#define libCSSCURRENCYCOUNT      8

//+------------------------------------------------------------------+
//| Release Notes                                                    |
//+------------------------------------------------------------------+
// v1.0.0, 5/7/13
// * Initial release
// * NanningBob's 10.5 rules apply
// v1.1.0, 8/2/13
// * Added getSlopeRSI
// * Changed to original NB rules
// v1.1.1, 8/5/13
// * Added getGlobalMarketTrend
// * Added parameters for caching mechanism
// v1.1.2, 9/6/13
// * Added flushCache parameter

bool    libCSSsundayCandlesDetected    = false;
bool    libCSSaddSundayToMonday        = false;
bool    libCSSuseOnlySymbolOnChart     = false;
string  libCSScacheSymbol              = "EURUSD";
int     libCSScacheTimeframe           = PERIOD_M1;
string  libCSSsymbolsToWeigh           = "GBPNZD,EURNZD,GBPAUD,GBPCAD,GBPJPY,GBPCHF,CADJPY,EURCAD,EURAUD,USDCHF,GBPUSD,EURJPY,NZDJPY,AUDCHF,AUDJPY,USDJPY,EURUSD,NZDCHF,CADCHF,AUDNZD,NZDUSD,CHFJPY,AUDCAD,USDCAD,NZDCAD,AUDUSD,EURCHF,EURGBP";
int     libCSSsymbolCount;
string  libCSSsymbolNames[];
string  libCSScurrencyNames[libCSSCURRENCYCOUNT]        = { "USD", "EUR", "GBP", "CHF", "JPY", "AUD", "CAD", "NZD" };
double  libCSScurrencyValues[libCSSCURRENCYCOUNT];      // Currency slope strength
double  libCSScurrencyOccurrences[libCSSCURRENCYCOUNT]; // Holds the number of occurrences of each currency in symbols

//+------------------------------------------------------------------+
//| libCSSinit()                                                    |
//+------------------------------------------------------------------+
void libCSSinit()
{
   libCSSinitSymbols();

   libCSSsundayCandlesDetected = false;
   for ( int i = 0; i < 8; i++ )
   {
      if ( TimeDayOfWeek( iTime( NULL, PERIOD_D1, i ) ) == 0 )
      {
         libCSSsundayCandlesDetected = true;
         break;
      }
   }
  
   return;
}
//+------------------------------------------------------------------+
//| Initialize Symbols Array                                         |
//+------------------------------------------------------------------+
int libCSSinitSymbols()
{
   int i;
   
   // Get extra characters on this crimmal's symbol names
   string symbolExtraChars = StringSubstrOld(Symbol(), 6, 4);

   // Trim user input
   libCSSsymbolsToWeigh = StringTrimLeft(libCSSsymbolsToWeigh);
   libCSSsymbolsToWeigh = StringTrimRight(libCSSsymbolsToWeigh);

   // Add extra comma
   if (StringSubstrOld(libCSSsymbolsToWeigh, StringLen(libCSSsymbolsToWeigh) - 1) != ",")
   {
      libCSSsymbolsToWeigh = StringConcatenate(libCSSsymbolsToWeigh, ",");   
   }   

   // Split user input
   i = StringFind( libCSSsymbolsToWeigh, "," ); 
   while ( i != -1 )
   {
      int size = ArraySize(libCSSsymbolNames);
      string newSymbol = StringConcatenate(StringSubstrOld(libCSSsymbolsToWeigh, 0, i), symbolExtraChars);
      if ( MarketInfo( newSymbol, MODE_TRADEALLOWED ) > libCSSEPSILON )
      {
         ArrayResize( libCSSsymbolNames, size + 1 );
         // Set array
         libCSSsymbolNames[size] = newSymbol;
      }
      // Trim symbols
      libCSSsymbolsToWeigh = StringSubstrOld(libCSSsymbolsToWeigh, i + 1);
      i = StringFind(libCSSsymbolsToWeigh, ","); 
   }
   
   // Kill unwanted symbols from array
   if ( libCSSuseOnlySymbolOnChart )
   {
      libCSSsymbolCount = ArraySize(libCSSsymbolNames);
      string tempNames[];
      for ( i = 0; i < libCSSsymbolCount; i++ )
      {
         for ( int j = 0; j < libCSSCURRENCYCOUNT; j++ )
         {
            if ( StringFind( Symbol(), libCSScurrencyNames[j] ) == -1 )
            {
               continue;
            }
            if ( StringFind( libCSSsymbolNames[i], libCSScurrencyNames[j] ) != -1 )
            {  
               size = ArraySize( tempNames );
               ArrayResize( tempNames, size + 1 );
               tempNames[size] = libCSSsymbolNames[i];
               break;
            }
         }
      }
      for ( i = 0; i < ArraySize( tempNames ); i++ )
      {
         ArrayResize( libCSSsymbolNames, i + 1 );
         libCSSsymbolNames[i] = tempNames[i];
      }
   }
   
   libCSSsymbolCount = ArraySize(libCSSsymbolNames);
   // Print("symbolCount: ", symbolCount);

   ArrayInitialize( libCSScurrencyOccurrences, 0.0 );
   for ( i = 0; i < libCSSsymbolCount; i++ )
   {
      // Increase currency occurrence
      int currencyIndex = libCSSgetCurrencyIndex(StringSubstrOld(libCSSsymbolNames[i], 0, 3));
      libCSScurrencyOccurrences[currencyIndex]++;
      currencyIndex = libCSSgetCurrencyIndex(StringSubstrOld(libCSSsymbolNames[i], 3, 3));
      libCSScurrencyOccurrences[currencyIndex]++;
   }  
   return(0); 
}

//+------------------------------------------------------------------+
//| getCurrencyIndex(string currency)                                |
//+------------------------------------------------------------------+
int libCSSgetCurrencyIndex(string currency)
{
   for (int i = 0; i < libCSSCURRENCYCOUNT; i++)
   {
      if (libCSScurrencyNames[i] == currency)
      {
         return(i);
      }   
   }   
   return (-1);
}

//+------------------------------------------------------------------+
//| getSlope()                                                       |
//+------------------------------------------------------------------+
double libCSSgetSlope( string symbol, int tf, int shift )
{
   double dblTma, dblPrev;
   int shiftWithoutSunday = shift;
   if ( libCSSaddSundayToMonday && libCSSsundayCandlesDetected && tf == PERIOD_D1 )
   {
      if ( TimeDayOfWeek( iTime( symbol, PERIOD_D1, shift ) ) == 0  ) shiftWithoutSunday++;
   }   
   double atr = iATR(symbol, tf, 100, shiftWithoutSunday + 10) / 10;
   double gadblSlope = 0.0;
   if ( atr != 0 )
   {
      dblTma = libCSScalcTmaTrue( symbol, tf, shiftWithoutSunday );
      dblPrev = libCSScalcPrevTrue( symbol, tf, shiftWithoutSunday );
      gadblSlope = ( dblTma - dblPrev ) / atr;
   }

   return ( gadblSlope );
}
//+------------------------------------------------------------------+
//| calcTmaTrue()                                                    |
//+------------------------------------------------------------------+
double libCSScalcTmaTrue( string symbol, int tf, int inx )
{
   return ( iMA( symbol, tf, 21, 0, MODE_LWMA, PRICE_CLOSE, inx ) );
}

//+------------------------------------------------------------------+
//| calcPrevTrue()                                                   |
//+------------------------------------------------------------------+
double libCSScalcPrevTrue( string symbol, int tf, int inx )
{
   double dblSum  = iClose( symbol, tf, inx + 1 ) * 21;
   double dblSumw = 21;
   int jnx, knx;
   
   dblSum  += iClose( symbol, tf, inx ) * 20;
   dblSumw += 20;
         
   for ( jnx = 1, knx = 20; jnx <= 20; jnx++, knx-- )
   {
      dblSum  += iClose( symbol, tf, inx + 1 + jnx ) * knx;
      dblSumw += knx;
   }
   
   return ( dblSum / dblSumw );
}
 
//+------------------------------------------------------------------+
//| getCSS( double& CSS[], int tf, int shift )                       |
//+------------------------------------------------------------------+
void libCSSgetCSS( double& css[], int tf, int shift, bool flushCache = true )
{
   static double volume;
   if ( flushCache || volume != iVolume(libCSScacheSymbol, libCSScacheTimeframe, 0) )
   {
      int i;
      
      ArrayInitialize(libCSScurrencyValues, 0.0);

      // Get Slope for all symbols and totalize for all currencies   
      for ( i = 0; i < libCSSsymbolCount; i++ )
      {
         double slope = libCSSgetSlope(libCSSsymbolNames[i], tf, shift);
         libCSScurrencyValues[libCSSgetCurrencyIndex(StringSubstrOld(libCSSsymbolNames[i], 0, 3))] += slope;
         libCSScurrencyValues[libCSSgetCurrencyIndex(StringSubstrOld(libCSSsymbolNames[i], 3, 3))] -= slope;
      }
      ArrayResize( css, libCSSCURRENCYCOUNT );
      for ( i = 0; i < libCSSCURRENCYCOUNT; i++ )
      {
         // average
         if ( libCSScurrencyOccurrences[i] > 0 ) libCSScurrencyValues[i] /= libCSScurrencyOccurrences[i]; else libCSScurrencyValues[i] = 0;
      }
   }
   for ( i = 0; i < libCSSCURRENCYCOUNT; i++ )
   {
      css[i] = libCSScurrencyValues[i];
   }
   volume = iVolume( libCSScacheSymbol, libCSScacheTimeframe, 0 );
}
//+------------------------------------------------------------------+
//| getCSSCurrency(string currency, int tf, int shift)               |
//+------------------------------------------------------------------+
double libCSSgetCSSCurrency( string currency, int tf, int shift )
{
   double css[];
   libCSSgetCSS( css, tf, shift, true );
   return ( css[libCSSgetCurrencyIndex(currency)] );
}

//+------------------------------------------------------------------+
//| getCSSdiff(int tf, int shift)                                    |
//+------------------------------------------------------------------+
double libCSSgetCSSDiff( string symbol, int tf, int shift )
{
   double css[];
   libCSSgetCSS( css, tf, shift, true );
   double diffLong = css[libCSSgetCurrencyIndex(StringSubstrOld(symbol, 0, 3))];
   double diffShort = css[libCSSgetCurrencyIndex(StringSubstrOld(symbol, 3, 3))];
   return ( diffLong - diffShort );
}

//+------------------------------------------------------------------+
//| getSlopeRSI( string symbol, int tf, int shift )                  |
//+------------------------------------------------------------------+
double libCSSgetSlopeRSI( string symbol, int tf, int shift )
{
   double slope[];
   int workPeriod = 17;                                         // RSI period Bob's default = 2, + overhead
   ArrayResize( slope, workPeriod );
   ArraySetAsSeries( slope, true );
   for ( int i = 0; i < workPeriod; i++ )
   {
      slope[i] = libCSSgetSlope( symbol, tf, shift + i );
   }
   return( iRSIOnArray( slope, workPeriod, 2, 0 ) );            // Again, 2 is Bob's default
}

//+------------------------------------------------------------------+
//| getBBonStoch( string symbol, int tf, int shift )                 |
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
//| getGlobalMarketTrend( int tf, int shift )                        |
//+------------------------------------------------------------------+
double libCSSgetGlobalMarketTrend( int tf, int shift ) 
{
   double buffer[libCSSCURRENCYCOUNT];
   libCSSgetCSS( buffer, tf, shift, true );
      
   double gmt = 0;
   for ( int i = 0; i < libCSSCURRENCYCOUNT; i++ )
   {
      gmt += MathPow(buffer[i], 2);
   }
   
   return ( gmt );
}

//+------------------------------------------------------------------+
//| NormalizeLots(string symbol, double lots)                        |
//+------------------------------------------------------------------+
//function added by fxdaytrader
//Lot size must be adjusted to be a multiple of lotstep, which may not be a power of ten on some brokers
//see also the original function by WHRoeder, http://forum.mql4.com/45425#564188, fxdaytrader
double NormalizeLots(string symbol, double lots) 
{
  if (MathAbs(lots)==0.0) return(0.0); //just in case ... otherwise it may happen that after rounding 0.0 the result is >0 and we have got a problem, fxdaytrader
  double ls = MarketInfo(symbol,MODE_LOTSTEP);
  lots = MathMin(MarketInfo(symbol,MODE_MAXLOT),MathMax(MarketInfo(symbol,MODE_MINLOT),lots)); //check if lots >= min. lots && <= max. lots, fxdaytrader
return(MathRound(lots/ls)*ls);
}

// for 6xx build compatibilità added by milanese

        string StringSubstrOld(string x,int a,int b=-1) {
        if (a < 0) a= 0; // Stop odd behaviour
        if (b<=0) b = -1; // new MQL4 EOL flag
        return StringSubstr(x,a,b);
        }
////////////////////////////////////////////////////////////////////////////////////////
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
//----
   //int cc;
   
   //In case the user wants fixed tp/sl
   if (TakeProfitPips > 0)
      TakeProfit = TakeProfitPips;
   if (StopLossPips > 0)
      StopLoss = StopLossPips;

   //Spread calculation
   if (CloseEnough(AverageSpread, 0) || RunInSpreadDetectionMode) 
   {
      GetAverageSpread();
      ScreenMessage = "";
      int left = TicksToCount - CountedTicks;
      SM("Calculating the average spread. " + DoubleToStr(left, 0) + " left to count.");
      Comment(ScreenMessage);
      return(0);
   }//if (CloseEnough(AverageSpread, 0) || RunInSpreadDetectionMode) 
   //Keep the average spread updated
   double spread = (Ask - Bid) * factor;
   if (spread > BiggestSpread) BiggestSpread = spread;//Widest spread since the EA was loaded
   static double SpreadTotal = 0;
   static int counter = 0;
   SpreadTotal+= spread;
   counter++;
   if (counter >= 500)
   {
      AverageSpread = NormalizeDouble(SpreadTotal / counter, 1);
      //Save the average for restarts.
      GlobalVariableSet(SpreadGvName, AverageSpread);
      SpreadTotal = 0;
      counter = 0;
   }//if (counter >= 500)
      
   //Create a flashing comment if there has been a rogue trade
   if (RobotSuspended) 
   {
      while (RobotSuspended)
      {
         Comment(NL, Gap, "****************** ROBOT SUSPENDED. POSSIBLE ROGUE TRADING ACTIVITY. REMOVE THIE EA IMMEDIATELY ****************** ");
         Sleep(2000);
         Comment("");
         Sleep(1000);
       }//while (RobotSuspended)           
      return(0);
   }//if (RobotSuspended) 

   
    //If HG is sleeping after a trade closure, is it time to awake?
   if (SafetyViolation) TooClose();
   if (SafetyViolation)//TooClose() sets SafetyViolation
   {
      DisplayUserFeedback();
      return(0);
   }//if (SafetyViolation) 
  
   /*
   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. 
   */
   if (TurnOff == 1) 
   {
      CalculateTradeProfitInPips(OP_BUY);//TurnOff is never 1, so the function is not called
      CloseEnough(1,1);
      DrawTrendLine("w", 0, 0, 0, 0, 0, 0, 0, true);
      DrawHorizontalLine("w", 0, 0, 0, 0);
      DrawVerticalLine("w", Red, STYLE_DASH, 0);
      libCSSgetCSSCurrency( Symbol(), 0, 0 );
      libCSSgetCSSDiff( Symbol(), 0, 0 );
      libCSSgetGlobalMarketTrend( 0, 0 );
   }//if (TurnOff == 1) 
   
   if (OrdersTotal() == 0)
   {
      TicketNo = -1;
      ForceTradeClosure = false;
   }//if (OrdersTotal() == 0)


   if (ForceTradeClosure) 
   {
      CloseAllTrades();
      return(0);
   }//if (ForceTradeClosure) 

   //Check for a massive spread widening event and pause the ea whilst it is happening
   CheckForSpreadWidening();

   GetSwap(Symbol() );//For the swap filters, and in case crim has changed swap rates
   
   double price = 0;
   //Is there a buy line on the chart?
   if (ObjectFind(0, buyline) > -1)
   {
      //Yes, so should it be deleted?
      if (TimeCurrent() >= (iTime(Symbol(), TF1, 0) + (LineDeletionMinutes * 60)) )
         ObjectDelete(0, buyline);
      else//Not deleted, so can it be traded
         HasBuyFilled();   
   }//if (ObjectFind(0, buyline) > -1)
   
   //Is there a sell line on the chart?
   if (ObjectFind(0, sellline) > -1)
   {
      //Yes, so should it be deleted?
      if (TimeCurrent() >= (iTime(Symbol(), TF1, 0) + (LineDeletionMinutes * 60)) )
         ObjectDelete(0, sellline);
      else//Not deleted, so can it be traded
         HasSellFilled();   
   }//if (ObjectFind(0, sellline) > -1)
   
// = ObjectGet(buyline, OBJPROP_PRICE1);

   //New candle. Cancel an existing alert sent. By default, all the email stuff is turned off, so this is probably redundant.
   static datetime OldAlertBarsTime;
   if (OldAlertBarsTime != iTime(NULL, TF1, 0) )
   {
      AlertSent = false;
      OldAlertBarsTime = iTime(NULL, TF1, 0);
   }//if (OldAlertBarsTimeBarsTime != iTime(NULL, 0, 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.
   CountOpenTrades();
   //Safety feature. Sometimes an unexpected concatenation of inputs choice and logic error can cause rapid opening-closing of trades. Detect a closed trade and check that is was not a rogue.
   if (OldOpenTrades != OpenTrades)
   {
      if (IsClosedTradeRogue() )
      {
         RobotSuspended = true;
         return(0);
      }//if (IsClosedTradeRogue() )      
   }//if (OldOpenTrades != OpenTrades)
   
   OldOpenTrades = OpenTrades;

   //Reset various bools
   if (OpenTrades == 0)
   {

   }//if (OpenTrades > 0)

   ///////////////////////////////////////////////////////////////////////////////////
  
   //Trading times
   TradeTimeOk = CheckTradingTimes();
   if (!TradeTimeOk)
   {
      DisplayUserFeedback();
      return(0);
   }//if (!TradeTimeOk)
   
   ///////////////////////////////////////////////////////////////////////////////////
  
   //Check that there is sufficient margin for trading
   if (!MarginCheck() )
   {
      DisplayUserFeedback();
      return(0);
   }//if (!MarginCheck() )
     
   //Trading
   if (EveryTickMode) OldBarsTime = 0;   
   if (OldBarsTime != iTime(NULL, TF1, 0) )
   {
      OldBarsTime = iTime(NULL, TF1, 0);
      ReadIndicatorValues();
      if (TicketNo == -1 && !StopTrading) LookForTradingOpportunities();
   }//if (TicketNo == -1)
   
   ///////////////////////////////////////////////////////////////////////////////////
  
   DisplayUserFeedback();


//----
   return(0);
}

//+------------------------------------------------------------------+
