//+------------------------------------------------------------------+
//|                             Nanningbob V5 auto trading robot.mq4 |
//|                                  Copyright © 2009, Steve Hopwood |
//|                              http://www.hopwood3.freeserve.co.uk |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Steve Hopwood"
#property link      "http://www.hopwood3.freeserve.co.uk"
#include <WinUser32.mqh>
#include <stdlib.mqh>
#define  NL    "\n"
#define  up "Up"
#define  down "Down"
#define  none "None"
#define  ranging "Ranging"
#define  confused "Confused, and so cannot trade"
#define  trending "Trending"
#define  irrelevant "Irrelevant - there is no trade direction yet"
#define  mode0 "Not looking for a trade trigger"
#define  mode1buy "#1 Buy"
#define  mode1sell "#1 Sell"
#define  mode2buy "#2 Buy"
#define  mode2sell "#2 Sell"
#define  mode3buy "#3 Buy BUlge"
#define  mode3sell "#3 Sell Bulge"
#define  mode4buy "#4 Buy"
#define  mode4sell "#4 Sell"
#define  opentrade "There is a trade open"

/*

Trading modes:
   - 0: not in trading zone
   - 1: #1 buy
   - 11: #1 sell
   - 2: #2 buy
   - 22: #2 sell
   - 3: #3 buy bulge
   - 33: #3 
   - 4: #4 buy
   - 44: #4 sell

----Trading----
bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take)
void AddReEntryLine(int type)
bool DoesTradeExist()


----Trading modes----
void Mode1Buy()
void Mode1Sell()
void Mode2Buy()
void Mode2Sell()
void Mode3Buy()
void Mode3Sell()
void Mode4Buy()
void Mode4Sell()


----Trade direction module----
void GetTradeDirection()
void IsDirectionStillValid()
void ReadIndicatorValues()
void GetBB()
void GetSixths()
void GetStoch()
double GetStochMACD(int fast_ema_period, int slow_ema_period, int signal_period, int StochasticPeriod, int shift)


----Trade closure module----
void TradeClosureModule()
bool WhiteLineClose(int type)
bool CloseTrade()

TREND DETECTION MODULE
----Trend direction----
void GetTheTrend()
void GetRsiTrend()
void GetAtrTrend()
void GetAdxTrend()
string GetLsmaTrend(int tf, int shift)

----Trade management module----
void TradeManagementModule()
void BreakEvenStopLoss()
bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop )
void JumpingStopLoss() 

*/

extern string  gen="----General inputs----";
extern double  Lot=0.1;
extern int     TakeProfit=0;
extern bool    UseAtrTp=true;
extern int     AtrTpPeriod=14;
extern int     AtrTpTimeFrame=0;
extern double  AtrTpMultiplier=3;
extern int     EmergencyStopLoss=999;
extern bool    CriminalIsECN=false;
extern int     ReEntryLinePips=200;
extern color   ReEntryLineColour=Turquoise;
extern string  six="----Sixths inputs----";
extern int     BarCount=120;
extern bool    TradeZoneA=false;
extern bool    TradeZoneB=true;
extern string  bl3="-------------------------------------------------------------";
extern string  tcm="----Trade closure module----";
extern string  wlc="White line closure";
extern bool    UseWhiteLineClosure=true;
extern int     MinSeperationFromBlue=15;
extern string  bl4="-------------------------------------------------------------";
extern string  tmm="----Trade management module----";
extern bool    DoNotOverload5DigitCriminals=true;
extern string  BE="Break even settings";
extern bool    BreakEven=true;
extern int     BreakEvenPips=25;
extern int     BreakEvenProfit=10;
extern bool    HideBreakEvenStop=false;
extern int     PipsAwayFromVisualBE=5;
extern string  JSL="Jumping stop loss settings";
extern bool    JumpingStop=true;
extern int     JumpingStopPips=50;
extern bool    AddBEP=true;
extern bool    JumpAfterBreakevenOnly=false;
extern bool    HideJumpingStop=false;
extern int     PipsAwayFromVisualJS=10;


extern string  bl1="-------------------------------------------------------------";
extern string  tm="----Trend detection module for #4----";
extern string  rsin="----Rsi----";
extern bool    UseRsi=true;
extern int     RsiTf=0;
extern int     RsiPeriod=21;
extern string  atri="----Atr----";
extern bool    UseAtr=false;
extern int     AtrTf=0;
extern int     AtrPeriod=21;
extern int     DaysToLookBack=10;
extern string  adxin="----Adx----";
extern bool    UseAdx=false;
extern int     AdxTf=0;
extern int     AdxPeriod=21;
extern string  ls="----LSMA----";
extern bool    UseLSMA=false;
extern int     LSMAPeriod=21;
extern int     LSMATf=0;
extern string  bl2="-------------------------------------------------------------";
extern string  smacd="----StochasticMacdSqualou inputs----";
extern int     FastEMA   =12;
extern int     SlowEMA   =26;
extern int     SignalSMA =9;
extern int     StochasticPeriod =120; //4 weeks of H4 bars = 4*5*24/4 = 120
extern int     OverBought=75;
extern int     OverSold=25;
extern string  mas="----MA inputs----";
extern double  MinSepFromBB=0.1;
extern string  mis="----Odds and ends----";
extern int     DisplayGapSize=30;
extern bool    ShowAlerts=true;

//-- info trade orders
//Corresponding trade comments
string no1_Buy25 = "#1 BUY_25";
string no1_Sel25 = "#1 SELL_25";

string no2_Buy1MA = "#2 BUY_1MA";
string no2_Sel1MA = "#2 SELL_1MA";

string no3_BuyBulge = "#3 BUY_Bulge";
string no3_SelBulge = "#3 SELL_Bulge";

string no4_BuyBB13 = "#4 BUY_BB13";
string no4_SelBB13 = "#4 SELL_BB13";

//Trading variables
int            TicketNo;

//BB variables
double         BbUpper, BbLower;

//6ths variable.
double         BottomGoldLine;//Bottom, gold line
double         BottomGreenLine;//Bottom, green line
double         MiddleWhiteLine;//Middle, white line
double         TopGreenLine;//Top, green line
double         TopGoldLine;//Top, gold line

//Stoch variables
double         StochWhite;
double         StochBlue;

//Macd
double         MacdVal;

//MA
double         Ma1;

//Trade direction
string         TradeDirection=none, TradingStatus=none;

//Trend
double         TrendRsiVal, TrendAtrVal;
double         AdxVal, AdxPlusDI, AdxMinusDI;
string         RsiTrend, AtrTrend, AdxTrend, LsmaTrend, trend;

//Misc
string         Gap, ScreenMessage, GvName;

void DisplayUserFeedback()
{
   if (IsTesting() && !IsVisualMode()) return;

   ScreenMessage = "";
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, 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;
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, m + " minutes " + s + " seconds left to bar end", NL);

   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "BB Upper line: ", DoubleToStr(BbUpper, Digits), NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "BB Lower line: ", DoubleToStr(BbLower, Digits), NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Sixths: ", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "    Top, gold line: ", DoubleToStr(TopGoldLine, Digits), NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "    Top, green line: ", DoubleToStr(TopGreenLine, Digits), NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "    Middle, white line: ", DoubleToStr(MiddleWhiteLine, Digits), NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "    Bottom, gold line: ", DoubleToStr(BottomGoldLine, Digits), NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "    Bottom, green line: ", DoubleToStr(BottomGreenLine, Digits), NL);
   if (TradeZoneA) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trading zone A (above top gold line and below bottom gold line)", NL);
   if (TradeZoneB) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trading zone B (above top green line and below bottom green line)", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Stochastic white line: ", StochWhite, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Stochastic blue line: ", StochBlue, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Macd red line: ", DoubleToStr(MacdVal, 4), NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "MA: ", DoubleToStr(Ma1, Digits), NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trade direction: ", TradeDirection, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trading status: ", TradingStatus, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "#4 trend: ", trend, NL);
   
   
      
/*
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);      
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Lot size: ", Lot, NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Take profit: ", TakeProfit, " pips",  NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Emergency stop loss: ", FontSize, " pips",  NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Magic number: ", MagicNumber, NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trade comment: ", TradeComment, NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Tolerance: ", Tolerance, NL);
      if (CriminalIsECN) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "CriminalIsECN = true", NL);
      else ScreenMessage = StringConcatenate(ScreenMessage,Gap, "CriminalIsECN = false", NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Criminal's minimum lot size: ", MarketInfo(Symbol(), MODE_MINLOT), NL, NL );
      if (CriminalAllowsHedging)
      {
         ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Hedging inputs:", NL);
         ScreenMessage = StringConcatenate(ScreenMessage,Gap, "      HedgeAtLossPips: ", HedgeAtLossPips, " pips", NL);
         //ScreenMessage = StringConcatenate(ScreenMessage,Gap, "      HedgeProfitTarget: ", HedgeProfitTarget, " pips", NL);
      }//if (CriminalAllowsHedging)
*/      
      Comment(ScreenMessage);


}//void DisplayUserFeedback()


//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
//----
   Gap="";
   if (DisplayGapSize >0)
   {
      for (int cc=0; cc< DisplayGapSize; cc++)
      {
         Gap = StringConcatenate(Gap, " ");
      }   
   }//if (DisplayGapSize >0)
   
   int multiplier;
   if(Digits == 2 || Digits == 4) multiplier = 1;
   if(Digits == 3 || Digits == 5) multiplier = 10;
   if(Digits == 6) multiplier = 100;   
   if(Digits == 7) multiplier = 1000;   
   
   TakeProfit*= multiplier;
   EmergencyStopLoss*= multiplier;
   ReEntryLinePips*= multiplier;
   BreakEvenPips*= multiplier;
   BreakEvenProfit*= multiplier;
   PipsAwayFromVisualBE*= multiplier;
   JumpingStopPips*= multiplier;
   PipsAwayFromVisualJS*= multiplier;
   
   
   GvName = "Nanningbob V5 " + Symbol();
   
   //Pick up looking for trade setups after a crash
   if (GlobalVariableCheck(GvName) ) int dir = GlobalVariableGet(GvName);
   TradeDirection = none;
   TradingStatus = mode0;
   
   //Market needs to touch the band from within
   if (dir == 1)
   {
      TradeDirection = up;
      TradingStatus = mode1buy;
   }//if (dir == 1)
   
   if (dir == 11)
   {
      TradeDirection = down;
      TradingStatus = mode1sell;
   }//if (dir == 1)
   
   //Market needs to sink back within the bands
   if (dir == 2)
   {
      TradeDirection = up;
      TradingStatus = mode2buy;
   }//if (dir == 2)
   
   if (dir == 22)
   {
      TradeDirection = down;
      TradingStatus = mode2sell;
   }//if (dir == 22)
   
   //Bulge
   if (dir == 3)
   {
      TradeDirection = up;
      TradingStatus = mode3buy;
   }//if (dir == 3)
   
   if (dir == 33)
   {
      TradeDirection = down;
      TradingStatus = mode3sell;
   }//if (dir == 33)
   
   
   

   //start();
   
//----
   return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
//----
   Comment("");
//----
   return(0);
}
///////////////////////////////////////////////////////////////////////////////////////////
//TREND DETECTION MODULE

void GetRsiTrend()
{
   //TrendRsiVal = GetRsi(0);
   trend = ranging;
   double tf = RsiTf;
   if (tf == 0) tf = Period();
   
   TrendRsiVal = iRSI(NULL, tf, RsiPeriod, PRICE_CLOSE, 0);

   if (TrendRsiVal > 55) RsiTrend = up;
   if (TrendRsiVal < 45) RsiTrend = down;
   

}//End void GetRsiTrend()


void GetAtrTrend()
{
   double PriceNow = Bid;
   double tf = AtrTf;
   if (AtrTf == 0) tf = Period();
   double ComparePrice = iOpen(NULL, tf, DaysToLookBack);
   
   TrendAtrVal = iATR(NULL, tf, AtrPeriod, 0);

   double x2TrendAtrVal = TrendAtrVal * 2;
   
   AtrTrend = ranging;
   if (PriceNow > ComparePrice) 
   {
      double TrendLevel = NormalizeDouble(ComparePrice + x2TrendAtrVal, Digits);
      if (Ask > TrendLevel) AtrTrend = up;
   }//if (PriceNow > ComparePrice) 
   
   if (PriceNow < ComparePrice) 
   {
      TrendLevel = NormalizeDouble(ComparePrice - x2TrendAtrVal, Digits);
      if (Bid < TrendLevel) AtrTrend = down;
   }//if (PriceNow > ComparePrice) 
   

}//End void GetAtrTrend()

void GetAdxTrend()
{
   AdxTrend = ranging;
   double tf = AdxTf;
   if (AdxTf == 0) tf = Period();
   double PreviousAdxVal = iADX(NULL, tf, AdxPeriod, PRICE_CLOSE, MODE_MAIN, 1);
   

   AdxVal = iADX(NULL, tf, AdxPeriod, PRICE_CLOSE, MODE_MAIN, 0);
   AdxPlusDI = iADX(NULL, tf, AdxPeriod, PRICE_CLOSE, MODE_PLUSDI, 0);
   AdxMinusDI = iADX(NULL, tf, AdxPeriod, PRICE_CLOSE, MODE_MINUSDI, 0);
   
   if (AdxVal < PreviousAdxVal) return;//No trend so nothing to do
   
   if (AdxPlusDI > AdxMinusDI)//trend is up
   {
      AdxTrend = up;
      return;
   }//if (AdxPlusDI > AdxMinusDI) 
   
   //Trend is neither up nor ranging
   AdxTrend = down;
   
}//End void GetAdxTrend()

double iLsma(int tf,int shift)
{
   //Code to calculate LSMA value. Copied from MrPip's work. Many thanks, MrPip
   
   double wt;
   
   double ma1=iMA(NULL,LSMATf,LSMAPeriod,0,MODE_SMA ,PRICE_CLOSE,shift);
   double ma2=iMA(NULL,LSMATf,LSMAPeriod,0,MODE_LWMA,PRICE_CLOSE,shift);
   wt = MathFloor((3.0*ma2-2.0*ma1)/Point) * Point;
   return(wt);
}//double iLsma(int LSMAPeriod,int shift)  

string GetLsmaTrend(int tf, int shift)
{
   LsmaTrend = ranging;
   double lsma_cur, lsma_prev;
   
   lsma_cur = iLsma(tf, shift);
   lsma_prev = iLsma(tf, shift + 1);
   if (lsma_cur > lsma_prev) LsmaTrend = up;
   if (lsma_cur < lsma_prev) LsmaTrend = down;
   
   return(LsmaTrend);

}//End string GetLsmaTrend()


void GetTheTrend()
{
   trend = "";
   string oldtrend = "";
   
   //Rsi
   if (UseRsi)
   {
      GetRsiTrend();
      trend = RsiTrend;
      oldtrend = trend;
   }//if (UseRsi)
   
   //Rsi
   if (UseAtr)
   {
      GetAtrTrend();
      trend = AtrTrend;
      if (trend != oldtrend && oldtrend != "")
      {
         trend = confused;
         return;
      }//if (trend != oldtrend)
      oldtrend = trend;
   }//if (UseRsi)
   
   //Axx
   if (UseAdx)
   {
      GetAdxTrend();
      trend = AdxTrend;
      if (trend != oldtrend && oldtrend != "")
      {
         trend = confused;
         return;
      }//if (trend != oldtrend)
      oldtrend = trend;
   }//if (UseRsi)
   
   //LSMA - MrPips
   if (UseLSMA)
   {
      string PrevTrend = GetLsmaTrend(LSMATf, 1);
      LsmaTrend = GetLsmaTrend(LSMATf, 0);  
      if (LsmaTrend == up && (PrevTrend == ranging || PrevTrend == down) ) trend = up;
      if (LsmaTrend == down && (PrevTrend == ranging || PrevTrend == up) ) trend = down;   
      trend = LsmaTrend;
      if (trend != oldtrend && oldtrend != "")
      {
         trend = confused;
         return;
      }//if (trend != oldtrend)
      oldtrend = trend;
   }//if (UseLSMA)
   //Alert(LsmaTrend);
   
   
}//End void GetTheTrend()


//END TREND DETECTION MODULE
///////////////////////////////////////////////////////////////////////////////////////////

void GetBB()
{
   //Reads BB figures into BbUpper, BbLower
   
   
   BbUpper = iBands(NULL, 0, 25, 2, 0, PRICE_OPEN, MODE_UPPER, 0);
   BbLower = iBands(NULL, 0, 25, 2, 0, PRICE_OPEN, MODE_LOWER, 0);
   
}//void GetBb()

bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take, int magic)
{
   
   //if (StopTrading) return(true);
   /*
   if (!IsTesting())
   {   
      if (!IsTradeAllowed() ) return(false);
      if (!IsConnected() ) return(false);
      if (!IsExpertEnabled() ) return(false);
      if (!IsTradeContextBusy() ) return(false);
   }//if (!IsTesting)
   */
   
   int slippage = 10;
   if (Digits == 3 || Digits == 5) slippage = 100;
   
   color col = Red;
   if (type == OP_BUY || type == OP_BUYSTOP) col = Green;
   
   int expiry = 0;
   //if (SendPendingTrades) expiry = TimeCurrent() + (PendingExpiryMinutes * 60);
   
   
   if (!CriminalIsECN) int ticket = OrderSend(Symbol(),type, lotsize, price, slippage, stop, take, comment, magic, expiry, col);
   
   
   //Is a 2 stage criminal
   if (CriminalIsECN)
   {
      ticket = OrderSend(Symbol(),type, lotsize, price, slippage, 0, 0, comment, magic, expiry, col);
	   if (stop != 0)
	   {
		   if (ticket > 0)
		   bool result = OrderModify(ticket, OrderOpenPrice(), stop, take, 0, CLR_NONE);
		   if (!result)
		   {
		       int err=GetLastError();
             Print(Symbol(), " ", type," SL  order modify failed with error(",err,"): ",ErrorDescription(err));               
		   }//if (!result)			  
	   }//if (Sl != 0)
      
      
   }//if (CriminalIsECN)
   
   //Error trapping for both
   if (ticket < 0)
   {
      string stype;
      if (type == OP_BUY) stype = "OP_BUY";
      if (type == OP_BUYSTOP) stype = "OP_BUYSTOP";
      if (type == OP_SELL) stype = "OP_SELL";
      if (type == OP_SELLSTOP) stype = "OP_SELLSTOP";
      err=GetLastError();
      Alert(Symbol(), " ", stype," Nanningbob order send failed with error(",err,"): ",ErrorDescription(err));
      Print(Symbol(), " ", stype," Nanningbob order send failed with error(",err,"): ",ErrorDescription(err));
      return(false);
   }//if (ticket < 0)  
   
   //Got this far, so trade send succeeded
   Sleep(5000);
   return(true);
   
}//End bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take)

bool DoesTradeExist()
{
   
   TicketNo = 0;
   
   if (OrdersTotal() == 0) return(false);
   
   for (int cc = OrdersTotal() - 1; cc >= 0 ; cc--)
   {
      if (!OrderSelect(cc,SELECT_BY_POS)) continue;
      
      if ( (OrderMagicNumber() > 0 && OrderMagicNumber() <= 4) && OrderSymbol() == Symbol() )      
      {
         TicketNo = OrderTicket();
         return(true);         
      }//if (OrderMagicNumber()==MagicNumber && OrderSymbol() == Symbol() )      
   }//for (int cc = OrdersTotal() - 1; cc >= 0 ; cc--)

   return(false);

}//End bool DoesTradeExist()


bool CloseTrade()
{
   bool result = OrderClose(TicketNo, OrderLots(), OrderClosePrice(), 1000, CLR_NONE);
   if (!result)
   {
      string stype;
      if (OrderType() == OP_BUY) stype = "OP_BUY";
      if (OrderType() == OP_BUYSTOP) stype = "OP_BUYSTOP";
      if (OrderType() == OP_SELL) stype = "OP_SELL";
      if (OrderType() == OP_SELLSTOP) stype = "OP_SELLSTOP";
      int err=GetLastError();
      Alert(Symbol(), " ", stype," Nanningbob order send failed with error(",err,"): ",ErrorDescription(err));
      Print(Symbol(), " ", stype," Nanningbob order send failed with error(",err,"): ",ErrorDescription(err));
      return(false);
   }//if (!result)
   
   return(true);
}//End bool CloseTrade()

void GetSixths()
{
   /*
   These are declared in the general section and count the lines from the bottom upwards
   double         BottomGoldLine;//Bottom, gold line
   double         BottomGreenLine;//Bottom, green line
   double         MiddleWhiteLine;//Middle, white line
   double         TopGreenLine;//Top, green line
   double         TopGoldLine;//Top, gold line

   */

   //double value = WindowPriceMax(0)-WindowPriceMin(0);      //value top of the chart - value buttem
   double value = High[iHighest(NULL,0,MODE_HIGH,BarCount,1)] - Low[iLowest(NULL,0,MODE_LOW,BarCount,1)];      //value top of the chart - value bottom
   double sixth = value/6;
   double valueS = (value*(MathPow(10,Digits)));
   double sixthS = (sixth*(MathPow(10,Digits)));
   
   BottomGoldLine = NormalizeDouble(Low[iLowest(NULL,0,MODE_LOW,BarCount,1)]+sixth, Digits);
   BottomGreenLine = NormalizeDouble(Low[iLowest(NULL,0,MODE_LOW,BarCount,1)]+sixth+sixth, Digits);
   MiddleWhiteLine = NormalizeDouble(Low[iLowest(NULL,0,MODE_LOW,BarCount,1)]+sixth+sixth+sixth, Digits);
   TopGreenLine = NormalizeDouble(Low[iLowest(NULL,0,MODE_LOW,BarCount,1)]+sixth+sixth+sixth+sixth, Digits);
   TopGoldLine = NormalizeDouble(Low[iLowest(NULL,0,MODE_LOW,BarCount,1)]+sixth+sixth+sixth+sixth+sixth, Digits);



}//End void GetSixths()

void GetStoch()
{
//double         StochWhite;
//double         StochRed;

   StochWhite = iStochastic(NULL, 0, 7, 3, 3, MODE_LWMA, 1, MODE_MAIN, 0);
   StochBlue = iStochastic(NULL, 0, 14, 3, 5, MODE_LWMA, 1, MODE_MAIN, 0);
   

}//void GetStoch();

double GetStochMACD(int fast_ema_period, int slow_ema_period, int signal_period, int StochasticPeriod, int shift)
{
  // get macd signal line
  double macdSignal;
  int j;
  // get highest/lowest of macdSignal over StochasticPeriod
  double ll = 100000, hh = -100000, dif;
  for(j=shift; j<shift+StochasticPeriod; j++)
  {
    macdSignal = iMACD(NULL,0,fast_ema_period, slow_ema_period, signal_period, PRICE_CLOSE,MODE_SIGNAL,j);
    hh = MathMax(hh,macdSignal);
    ll = MathMin(ll,macdSignal);
  }

  // normalize to 0..100

  dif = hh-ll;
  if (dif==0) return (0);
  else return (100 * (iMACD(NULL,0,fast_ema_period, slow_ema_period, signal_period, PRICE_CLOSE,MODE_SIGNAL,shift)-ll)/dif); 
}//End double GetStochMACD(int fast_ema_period, int slow_ema_period, int signal_period, int StochasticPeriod, int shift)

void GetMA()
{
   
   Ma1 = iMA(NULL, 0, 1, 0, MODE_SMA, PRICE_CLOSE, 0);

}//void GetMA();


void ReadIndicatorValues()
{


   GetBB();//Bollinger Bands
   GetSixths();
   GetStoch();
   MacdVal = GetStochMACD(FastEMA, SlowEMA, SignalSMA, StochasticPeriod , 0);
   GetMA();

}//End void ReadIndicatorValues()


void GetTradeDirection()
{
   
   /*
   These variables are used in the screen display.
   Their corresponding values are stored in a global to allow the robot to pick up smoothly
   in the event of a system/platform crash.
   #define  DropBelowBbUpper "Waiting for the market to drop below BB high line" // 0
   #define  TouchBbUpper "Waiting for the market to touch BB high line" // 1
   #define  RiseAboveBbLower "Waiting for the market to rise above BB low line" // 2
   #define  TouchBbLower "Waiting for the market to touch the BB low line" // 3
   */
   trend = irrelevant;
   
   //Is market in the killing zone
   if (Ask <= TopGreenLine && Ask >= BottomGreenLine && Bid <= TopGreenLine && Bid >= BottomGreenLine)
   {
      TradeDirection = none;
      TradingStatus = none;
      GlobalVariableDel(GvName);
      return;
   }//if (Ask <= TopGreenLine && Ask >= BottomGreenLine Bid <= TopGreenLine && Bid >= BottomGreenLine)
   
   if (TradeZoneA) double target = TopGoldLine;
   if (TradeZoneB) target = TopGreenLine;


   /*
   Bollinger Bands %b measures the market distance from BB Upperline, so a value of 1 means the
   market is equal the top line; 0 = bottom line; 0.5 = middle line etc. This indi can be used
   to show if there is a decent separation between BB and market
   */
   double BbSeparation = iCustom(NULL, 0, "Bollinger Bands %b", 25, 2, 0, 0, 0);
   double BbBandwidth = iCustom(NULL, 0, "Bandwidth Indicator", 0, 25, 2, 0, 0, 0, 0);
   
   
   //Check for short direction trade setup
   if (Ask > target)
   {
      TradeDirection = down;
      if (StochBlue < 85) TradeDirection = none;
      if (MacdVal < OverBought) TradeDirection = none;
      if (BbUpper < TopGreenLine) TradeDirection = none;
      //if (MathAbs(BbUpper - Ma1) < MinSepFromBB * Point) TradeDirection = none;
      if (MathAbs(BbUpper - BbSeparation) < MinSepFromBB) TradeDirection = none;
      if (TradeDirection == down)
      {
         //#1
         if (Ask < BbUpper)
         {
            TradingStatus = mode1sell;
            GlobalVariableSet(GvName, 11);
         }//if (Ask >= BbUpper)
         
         //#2
         if (Ask >= BbUpper)
         {
            TradingStatus = mode2sell;
            GlobalVariableSet(GvName, 22);
         }//if (Ask >= BbUpper)
         
         //#3
         double screentop = WindowPriceMax(0);   
         if (BbUpper >= screentop) 
         {
            TradingStatus = mode3sell;
            GlobalVariableSet(GvName, 33);
         }//if (BbUpper >= screentop)) 
         
         // alternatively, if this misses valid bulge buys and sell because of screen refresh, could use this code 
         /* 
         double value = screentop - screenbottom      //value top of the chart - value bottom
         double sixth = value/6;
         double valueS = (value*(MathPow(10,Digits)));
         double sixthS = (sixth*(MathPow(10,Digits)));

         double BulgeBottom = NormalizeDouble(screenbottom+sixth/2, Digits);
         double BulgeTop = NormalizeDouble(screentop-sixth/2, Digits);

         if ( (BbUpper >= BulgeTop) || (BbLower <= BulgeBottom) ) */

   
         //#4
         GetTheTrend();
         if (trend == ranging)
         {
            TradingStatus = mode4sell;
            GlobalVariableSet(GvName, 44);
         }//if (trend == ranging)
         
         
      }//if (TradeDirection == down)
      
   }//if (Ask > target)

   if (TradeZoneA) target = BottomGoldLine;
   if (TradeZoneB) target = BottomGreenLine;

   //Check for short direction trade setup
   if (Bid < target)
   {
      TradeDirection = up;
      if (StochBlue > 15 ) TradeDirection = none;
      if (MacdVal > OverSold) TradeDirection = none;
      if (BbLower > BottomGreenLine) TradeDirection = none;
      //if (MathAbs(BbLower - Ma1) < MinSepFromBB * Point) TradeDirection = none;
      if (MathAbs(BbLower - BbSeparation) < MinSepFromBB) TradeDirection = none;
      
      if (TradeDirection == up)
      {
         //#1
         if (Bid > BbLower)
         {
            TradingStatus = mode1buy;
            GlobalVariableSet(GvName, 1);
         }//if (Ask >= BbUpper)
         
         //#2
         if (Bid <= BbLower)
         {
            TradingStatus = mode2buy;
            GlobalVariableSet(GvName, 2);
         }//if (Bid <= BbLower)

         //#3
         double screenbottom = WindowPriceMin(0);   
         if (BbLower <= screenbottom) 
         {
            TradingStatus = mode3buy;
            GlobalVariableSet(GvName, 3);
         }//if (BbLower <= screenbottom) 

         //#4
         GetTheTrend();
         if (trend == ranging)
         {
            TradingStatus = mode4buy;
            GlobalVariableSet(GvName, 4);
         }//if (trend == ranging)
         
      
      }//if (TradeDirection == up)
         
         
   }//if (Bid < target)



}//End void GetTradeDirection()

void IsDirectionStillValid()
{
   
   if (Ask <= TopGreenLine && Ask >= BottomGreenLine && Bid <= TopGreenLine && Bid >= BottomGreenLine)
   {
      TradeDirection = none;
      TradingStatus = none;
      GlobalVariableSet(GvName, 0);
   }//if (Ask <= TopGreenLine && Ask >= BottomGreenLine Bid <= TopGreenLine && Bid >= BottomGreenLine)
   

}//void IsDirectionStillValid()

void AddReEntryLine(int type)
{

      RefreshRates();
      
      if (type == OP_BUY)
      {
         double LinePrice = NormalizeDouble(Ask - (ReEntryLinePips * Point), Digits);
         ObjectCreate("Re entry line",OBJ_HLINE,0,TimeCurrent(),LinePrice);
         ObjectSet("Re entry line",OBJPROP_COLOR,ReEntryLineColour);
         ObjectSet("Re entry line",OBJPROP_STYLE,STYLE_SOLID);
         ObjectSet("Re entry line",OBJPROP_WIDTH,2);     

      }//if (type == OP_BUY)
      
      if (type == OP_SELL)
      {
         LinePrice = NormalizeDouble(Bid + (ReEntryLinePips * Point), Digits);
         ObjectCreate("Re entry line",OBJ_HLINE,0,TimeCurrent(),LinePrice);
         ObjectSet("Re entry line",OBJPROP_COLOR,ReEntryLineColour);
         ObjectSet("Re entry line",OBJPROP_STYLE,STYLE_SOLID);
         ObjectSet("Re entry line",OBJPROP_WIDTH,2);     

      }//if (type == OP_SELL)



}//void AddReEntryLine(int type)

bool WhiteLineClose(int type)
{
//extern bool    UseWhiteLineClosure=true;
//extern int     MinSeperationFromBlue=15;

   if (OrderProfit() < 0) return(false);
   
   if (type == OP_BUY)
   {
      if (StochWhite > 85 && StochWhite - StochBlue > MinSeperationFromBlue) return(true);
   }//if (type == OP_BUY)
      
   if (type == OP_SELL)
   {
      if (StochWhite < 15 && StochBlue - StochWhite > MinSeperationFromBlue) return(true);
   }//if (type == OP_BUY)
      

   return(false);

}//bool WhiteLineClose(int type)


void TradeClosureModule()
{


   bool CloseRequired = false;
   
   //White line closure
   if (!CloseRequired)
   {
      if (UseWhiteLineClosure)
      {
         CloseRequired = WhiteLineClose(OrderType() );
      }//if (UseWhiteLineClosure)
      
   }//if (!CloseRequired)
   

   if (CloseRequired) CloseTrade();

}//void TradeClosureModule()



void Mode1Buy()
{
   //Equates to #1 Buy 25 BB
   if (DoesTradeExist()) return;
   if (ObjectFind("Re entry line") > -1) ObjectDelete("Re entry line");

   RefreshRates();
   if (Bid < BbLower)
   {
      double stop = NormalizeDouble(Ask - (EmergencyStopLoss * Point),Digits);
      if (EmergencyStopLoss == 0) stop = 0;
      double take = NormalizeDouble(Ask + (TakeProfit * Point),Digits);
      if (TakeProfit == 0) take = 0;
      //There is the option for the user to use Atr to calculate the stop
      if (UseAtrTp) 
      {
         double AtrVal = iATR(Symbol(), AtrTpTimeFrame, AtrTpPeriod, 0) * AtrTpMultiplier;
         take = NormalizeDouble(Ask + AtrVal,Digits);
      }//if (UseAtrTp) 
      bool result = SendSingleTrade(OP_BUY, no1_Buy25, Lot, Ask, stop, take, 1);
      if (result) 
      {
         GlobalVariableSet(GvName, 0);
         TradingStatus = opentrade;
         AddReEntryLine(OP_BUY);
      }//if (result) 
      
   }//if (Bid < BbLower)
 
}//void Mode1Buy()

void Mode1Sell()
{
   //Equates to #1 Sell 25 BB
   if (DoesTradeExist()) return;
   if (ObjectFind("Re entry line") > -1) ObjectDelete("Re entry line");

   RefreshRates();
   if (Bid > BbUpper)
   {
      double stop = NormalizeDouble(Bid + (EmergencyStopLoss * Point),Digits);
      if (EmergencyStopLoss == 0) stop = 0;
      double take = NormalizeDouble(Bid - (TakeProfit * Point),Digits);
      if (TakeProfit == 0) take = 0;
      if (UseAtrTp) 
      {
         double AtrVal = iATR(Symbol(), AtrTpTimeFrame, AtrTpPeriod, 0) * AtrTpMultiplier;
         take = NormalizeDouble(Bid - AtrVal,Digits);
      }//if (UseAtrTp) 
      bool result = SendSingleTrade(OP_SELL, no1_Sel25, Lot, Bid, stop, take, 1);
      if (result) 
      {
         GlobalVariableSet(GvName, 0);
         TradingStatus = opentrade;
         AddReEntryLine(OP_SELL);
      }//if (result) 

   }//if (Ask > BbUpper)


}//void Mode1Sell()

void Mode2Buy()
{

   //Equates to #1 Buy 1 MA 25 BB
   if (DoesTradeExist()) return;
   if (ObjectFind("Re entry line") > -1) ObjectDelete("Re entry line");

   RefreshRates();
   
   double  Var1, Var2;
   //---- indicators
   
   // MOVING AVERAGE
   Var1 = iMA(NULL, PERIOD_H4,  1, 0, MODE_LWMA, PRICE_MEDIAN,  0);
   //Var2 = iMA(NULL, PERIOD_H4,  2, 0, MODE_LWMA, PRICE_MEDIAN,  1);

   BbLower = iBands(NULL, PERIOD_H4,  25, 2, 0, PRICE_CLOSE, MODE_LOWER, 0); 

   BbUpper = iBands(NULL, PERIOD_H4,  25, 2, 0, PRICE_CLOSE, MODE_UPPER, 0);
 
   RefreshRates();
   if (Var1 > BbLower)
   {
      double stop = NormalizeDouble(Ask - (EmergencyStopLoss * Point),Digits);
      if (EmergencyStopLoss == 0) stop = 0;
      double take = NormalizeDouble(Ask + (TakeProfit * Point),Digits);
      if (TakeProfit == 0) take = 0;
      if (UseAtrTp) 
      {
         double AtrVal = iATR(Symbol(), AtrTpTimeFrame, AtrTpPeriod, 0) * AtrTpMultiplier;
         take = NormalizeDouble(Ask + AtrVal,Digits);
      }//if (UseAtrTp) 
      bool result = SendSingleTrade(OP_BUY, no2_Buy1MA, Lot, Ask, stop, take, 2);
      if (result) 
      {
         GlobalVariableSet(GvName, 0);
         TradingStatus = opentrade;
         AddReEntryLine(OP_BUY);
      }//if (result) 

   }//if (Var2 < BbLower && Var1 > BbLower)


}//void Mode2Buy()

void Mode2Sell()
{

   //Equates to #1 Sell 1 MA 25 BB
   if (DoesTradeExist()) return;
   if (ObjectFind("Re entry line") > -1) ObjectDelete("Re entry line");

   RefreshRates();

   double  Var1, Var2;
   //---- indicators
   
   // MOVING AVERAGE
   Var1 = iMA(NULL, PERIOD_H4,  1, 0, MODE_LWMA, PRICE_MEDIAN,  0);
   //Var2 = iMA(NULL, PERIOD_H4,  2, 0, MODE_LWMA, PRICE_MEDIAN,  1);

   BbLower = iBands(NULL, PERIOD_H4,  25, 2, 0, PRICE_CLOSE, MODE_LOWER, 0); 

   BbUpper = iBands(NULL, PERIOD_H4,  25, 2, 0, PRICE_CLOSE, MODE_UPPER, 0);
 
   RefreshRates();
   //if (Var2 > BbUpper && Var1 < BbUpper)
   if( Var1 < BbUpper)
   {
      double stop = NormalizeDouble(Bid + (EmergencyStopLoss * Point),Digits);
      if (EmergencyStopLoss == 0) stop = 0;
      double take = NormalizeDouble(Bid - (TakeProfit * Point),Digits);
      if (TakeProfit == 0) take = 0;
      if (UseAtrTp) 
      {
         double AtrVal = iATR(Symbol(), AtrTpTimeFrame, AtrTpPeriod, 0) * AtrTpMultiplier;
         take = NormalizeDouble(Bid - AtrVal,Digits);
      }//if (UseAtrTp) 
      bool result = SendSingleTrade(OP_SELL, no2_Sel1MA, Lot, Bid, stop, take, 2);
      if (result) 
      {
         GlobalVariableSet(GvName, 0);
         TradingStatus = opentrade;
         AddReEntryLine(OP_SELL);
      }//if (result) 

   }//if( Var1 < BbUpper)

}//void Mode2Sell()

void Mode3Buy()
{

   //Equates to #1 Buy 1 MA 25 BB
   if (DoesTradeExist()) return;
   if (ObjectFind("Re entry line") > -1) ObjectDelete("Re entry line");

   
   double  Var1, Var2, Var3;
   //---- indicators
   
   // MOVING AVERAGE
   Var1 = iMA(NULL, PERIOD_H4, 1, 0, MODE_LWMA, PRICE_MEDIAN,  0);
   Var2 = iMA(NULL, PERIOD_H4, 4, 0, MODE_LWMA, PRICE_LOW,  0);
   Var3 = iMA(NULL, PERIOD_H4, 4, 0, MODE_LWMA, PRICE_HIGH,  0);
    
   
   BbLower = iBands(NULL, PERIOD_H4,  25, 2, 0, PRICE_CLOSE, MODE_LOWER, 0); 

   BbUpper = iBands(NULL, PERIOD_H4,  25, 2, 0, PRICE_CLOSE, MODE_UPPER, 0);
 
   RefreshRates();
   if(Bid < Var2 && Var1 > BbLower)
   {
      double stop = NormalizeDouble(Ask - (EmergencyStopLoss * Point),Digits);
      if (EmergencyStopLoss == 0) stop = 0;
      double take = NormalizeDouble(Ask + (TakeProfit * Point),Digits);
      if (TakeProfit == 0) take = 0;
      if (UseAtrTp) 
      {
         double AtrVal = iATR(Symbol(), AtrTpTimeFrame, AtrTpPeriod, 0) * AtrTpMultiplier;
         take = NormalizeDouble(Ask + AtrVal,Digits);
      }//if (UseAtrTp) 
      bool result = SendSingleTrade(OP_BUY, no3_BuyBulge, Lot, Ask, stop, take, 3);
      if (result) 
      {
         GlobalVariableSet(GvName, 0);
         TradingStatus = opentrade;
         AddReEntryLine(OP_BUY);
      }//if (result) 

      
   }//if(Bid < Var2 && Var1 > BbLower)
    
    


}//void Mode3Buy()

void Mode3Sell()
{

   //Equates to #1 Sell 1 MA 25 BB
   if (DoesTradeExist()) return;
   if (ObjectFind("Re entry line") > -1) ObjectDelete("Re entry line");

   double  Var1, Var2, Var3;
   //---- indicators
   
   // MOVING AVERAGE
   Var1 = iMA(NULL, PERIOD_H4, 1, 0, MODE_LWMA, PRICE_MEDIAN,  0);
   Var2 = iMA(NULL, PERIOD_H4, 4, 0, MODE_LWMA, PRICE_LOW,  0);
   Var3 = iMA(NULL, PERIOD_H4, 4, 0, MODE_LWMA, PRICE_HIGH,  0);
    

   BbLower = iBands(NULL, PERIOD_H4,  25, 2, 0, PRICE_CLOSE, MODE_LOWER, 0); 

   BbUpper = iBands(NULL, PERIOD_H4,  25, 2, 0, PRICE_CLOSE, MODE_UPPER, 0);
 
   RefreshRates();
   //if (Var2 > BbUpper && Var1 < BbUpper)
   if(Bid  > Var3 && Var1 < BbUpper)
   {
      double stop = NormalizeDouble(Bid + (EmergencyStopLoss * Point),Digits);
      if (EmergencyStopLoss == 0) stop = 0;
      double take = NormalizeDouble(Bid - (TakeProfit * Point),Digits);
      if (TakeProfit == 0) take = 0;
      if (UseAtrTp) 
      {
         double AtrVal = iATR(Symbol(), AtrTpTimeFrame, AtrTpPeriod, 0) * AtrTpMultiplier;
         take = NormalizeDouble(Bid - AtrVal,Digits);
      }//if (UseAtrTp) 
      bool result = SendSingleTrade(OP_SELL, no3_SelBulge, Lot, Bid, stop, take, 3);
      if (result) 
      {
         GlobalVariableSet(GvName, 0);
         TradingStatus = opentrade;
         AddReEntryLine(OP_SELL);
      }//if (result) 

   }//if(Bid  > Var3 && Var1 < BbUpper)

}//void Mode3Sell()

void Mode4Buy()
{

   //Equates to #1 Buy 1 MA 25 BB
   if (DoesTradeExist()) return;
   if (ObjectFind("Re entry line") > -1) ObjectDelete("Re entry line");

   
   BbLower = iBands(NULL, PERIOD_H4,  25, 2, 0, PRICE_CLOSE, MODE_LOWER, 0); 

   BbUpper = iBands(NULL, PERIOD_H4,  25, 2, 0, PRICE_CLOSE, MODE_UPPER, 0);
 
   double Var1 = iMA(NULL, PERIOD_H4,  1, 0, MODE_LWMA, PRICE_MEDIAN,  0);
   double Var2 = iMA(NULL, PERIOD_H4,  3, 1, MODE_LWMA, PRICE_MEDIAN,  0);
 
   RefreshRates();
   if (Bid  < BbLower || (Bid > Var2 && Var1 < Var2))
   {
      double stop = NormalizeDouble(Ask - (EmergencyStopLoss * Point),Digits);
      if (EmergencyStopLoss == 0) stop = 0;
      double take = NormalizeDouble(Ask + (TakeProfit * Point),Digits);
      if (TakeProfit == 0) take = 0;
      bool result = SendSingleTrade(OP_BUY, no4_BuyBB13, Lot, Ask, stop, take, 4);
      if (result) 
      {
         GlobalVariableSet(GvName, 0);
         TradingStatus = opentrade;
         AddReEntryLine(OP_BUY);
      }//if (result) 

      
   }//if (Bid  < BbLower || (Bid > Var2 && Var1 < Var2))
    
    
}//void Mode4Buy()

void Mode4Sell()
{

   //Equates to #1 Sell 1 MA 25 BB
   if (DoesTradeExist()) return;
   if (ObjectFind("Re entry line") > -1) ObjectDelete("Re entry line");

   BbLower = iBands(NULL, PERIOD_H4,  25, 2, 0, PRICE_CLOSE, MODE_LOWER, 0); 

   BbUpper = iBands(NULL, PERIOD_H4,  25, 2, 0, PRICE_CLOSE, MODE_UPPER, 0);

   double Var1 = iMA(NULL, PERIOD_H4,  1, 0, MODE_LWMA, PRICE_MEDIAN,  0);
   double Var2 = iMA(NULL, PERIOD_H4,  3, 1, MODE_LWMA, PRICE_MEDIAN,  0);
 
   RefreshRates();
   if(Bid  > BbUpper || (Bid < Var2 && Var1 > Var2))
   {
      double stop = NormalizeDouble(Bid + (EmergencyStopLoss * Point),Digits);
      if (EmergencyStopLoss == 0) stop = 0;
      double take = NormalizeDouble(Bid - (TakeProfit * Point),Digits);
      if (TakeProfit == 0) take = 0;
      bool result = SendSingleTrade(OP_SELL, no4_SelBB13, Lot, Bid, stop, take, 4);
      if (result) 
      {
         GlobalVariableSet(GvName, 0);
         TradingStatus = opentrade;
         AddReEntryLine(OP_SELL);
      }//if (result) 

      
   }//if(Bid  > BbUpper || (Bid < Var2 && Var1 > Var2))
    
}//void Mode4Sell()

bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop )
{
   //Reusable code that can be called by any of the stop loss manipulation routines except HiddenStopLoss().
   //Checks to see if the market has hit the hidden sl and attempts to close the trade if so. 
   //Returns true if trade closure is successful, else returns false
   
   //Check buy trade
   if (type == OP_BUY)
   {
      double sl = NormalizeDouble(stop + (iPipsAboveVisual * Point), Digits);
      if (Bid <= sl)
      {
         bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {
            if (ShowAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            int err=GetLastError();
            if (ShowAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (Bid <= sl)  
   }//if (type = OP_BUY)
   
   //Check buy trade
   if (type == OP_SELL)
   {
      sl = NormalizeDouble(stop - (iPipsAboveVisual * Point), Digits);
      if (Ask >= sl)
      {
         result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {
            if (ShowAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            err=GetLastError();
            if (ShowAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (Ask >= sl)  
   }//if (type = OP_SELL)
   

}//End bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop )


void BreakEvenStopLoss() // Move stop loss to breakeven
{

   //Check hidden BE for trade closure
   if (HideBreakEvenStop)
   {
      bool TradeClosed = CheckForHiddenStopLossHit(OrderType(), PipsAwayFromVisualBE, OrderStopLoss() );
      if (TradeClosed) return;//Trade has closed, so nothing else to do
   }//if (HideBreakEvenStop)


   bool result;

           
   if (OrderType()==OP_BUY)
         {
            if (Bid >= OrderOpenPrice () + (Point*BreakEvenPips) && 
                OrderStopLoss()<OrderOpenPrice())
            {
               result = OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+(BreakEvenProfit*Point),OrderTakeProfit(),0,CLR_NONE);
               if (result && ShowAlerts==true) Alert("Breakeven set on ", OrderSymbol(), " ticket no ", OrderTicket());
               Print("Breakeven set on ", OrderSymbol(), " ticket no ", OrderTicket());
               if (!result)
               {
                  int err=GetLastError();
                  if (ShowAlerts==true) Alert("Setting of breakeven SL ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
                  Print("Setting of breakeven SL ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
               }//if !result && ShowAlerts)      
               //if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
               //{
               //   bool PartCloseSuccess = PartCloseTradeFunction();
               //   if (!PartCloseSuccess) SetAGlobalTicketVariable();
               //}//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
            }
   	   }               			         
          
   if (OrderType()==OP_SELL)
         {
           if (Ask <= OrderOpenPrice() - (Point*BreakEvenPips) &&
              (OrderStopLoss()>OrderOpenPrice()|| OrderStopLoss()==0)) 
            {
               result = OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-(BreakEvenProfit*Point),OrderTakeProfit(),0,CLR_NONE);
               if (result && ShowAlerts==true) Alert("Breakeven set on ", OrderSymbol(), " ticket no ", OrderTicket());
               Print("Breakeven set on ", OrderSymbol(), " ticket no ", OrderTicket());
               if (!result && ShowAlerts)
               {
                  err=GetLastError();
                  if (ShowAlerts==true) Alert("Setting of breakeven SL ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
                  Print("Setting of breakeven SL ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
               }//if !result && ShowAlerts)      
              //if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
              // {
              //    PartCloseSuccess = PartCloseTradeFunction();
              //    if (!PartCloseSuccess) SetAGlobalTicketVariable();
              // }//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
            }    
         }
      

} // End BreakevenStopLoss sub

void JumpingStopLoss() 
{
   // Jump sl by pips and at intervals chosen by user .
   // Also carry out partial closure if the user requires this

   // Abort the routine if JumpAfterBreakevenOnly is set to true and be sl is not yet set
   if (JumpAfterBreakevenOnly && OrderType()==OP_BUY)
   {
      if(OrderStopLoss()<OrderOpenPrice()) return(0);
   }
  
   if (JumpAfterBreakevenOnly && OrderType()==OP_SELL)
   {
      if(OrderStopLoss()>OrderOpenPrice()) return(0);
   }
  
   double sl=OrderStopLoss(); //Stop loss

   if (OrderType()==OP_BUY)
   {
      //Check hidden js for trade closure
      if (HideJumpingStop)
      {
         bool TradeClosed = CheckForHiddenStopLossHit(OP_BUY, PipsAwayFromVisualJS, OrderStopLoss() );
         if (TradeClosed) return;//Trade has closed, so nothing else to do
      }//if (HideJumpingStop)
      
      // First check if sl needs setting to breakeven
      if (sl==0 || sl<OrderOpenPrice())
      {
         if (Ask >= OrderOpenPrice() + (JumpingStopPips*Point))
         {
            sl=OrderOpenPrice();
            if (AddBEP==true) sl=sl+(BreakEvenProfit*Point); // If user wants to add a profit to the break even
            bool result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
            if (result)
            {
               if (ShowAlerts==true) Alert("Jumping stop set at breakeven ",sl, " ", OrderSymbol(), " ticket no ", OrderTicket());
               Print("Jumping stop set at breakeven: ", OrderSymbol(), ": SL ", sl, ": Ask ", Bid);
               //if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
               //{
                  //bool PartCloseSuccess = PartCloseTradeFunction();
                  //if (!PartCloseSuccess) SetAGlobalTicketVariable();
               //}//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
            }//if (result)
            if (!result)
            {
               int err=GetLastError();
               if (ShowAlerts) Alert(OrderSymbol(), " buy trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err));
               Print(OrderSymbol(), " buy trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err));
            }//if (!result)
             
            return(0);
         }//if (Ask >= OrderOpenPrice() + (JumpingStopPips*Point))
      } //close if (sl==0 || sl<OrderOpenPrice()

  
      // Increment sl by sl + JumpingStopPips.
      // This will happen when market price >= (sl + JumpingStopPips)
      if (Bid>= sl + ((JumpingStopPips*2)*Point) && sl>= OrderOpenPrice())      
      {
         sl=sl+(JumpingStopPips*Point);
         result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
         if (result)
         {
            if (ShowAlerts==true) Alert("Jumping stop set at ",sl, " ", OrderSymbol(), " ticket no ", OrderTicket());
            Print("Jumping stop set: ", OrderSymbol(), ": SL ", sl, ": Ask ", Ask);
            //if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
            //{
               //PartCloseSuccess = PartCloseTradeFunction();
               //if (!PartCloseSuccess) SetAGlobalTicketVariable();
            //}//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
         }//if (result)
         if (!result)
         {
            err=GetLastError();
            if (ShowAlerts) Alert(OrderSymbol(), " buy trade. Jumping stop function failed with error(",err,"): ",ErrorDescription(err));
            Print(OrderSymbol(), " buy trade. Jumping stop function failed with error(",err,"): ",ErrorDescription(err));
         }//if (!result)
             
      }// if (Bid>= sl + (JumpingStopPips*Point) && sl>= OrderOpenPrice())      
   }//if (OrderType()==OP_BUY)
   
   if (OrderType()==OP_SELL)
   {
      //Check hidden js for trade closure
      if (HideJumpingStop)
      {
         TradeClosed = CheckForHiddenStopLossHit(OP_SELL, PipsAwayFromVisualJS, OrderStopLoss() );
         if (TradeClosed) return;//Trade has closed, so nothing else to do
      }//if (HideJumpingStop)
            
      // First check if sl needs setting to breakeven
      if (sl==0 || sl>OrderOpenPrice())
      {
         if (Ask <= OrderOpenPrice() - (JumpingStopPips*Point))
         {
            sl = OrderOpenPrice();
            if (AddBEP==true) sl=sl-(BreakEvenProfit*Point); // If user wants to add a profit to the break even
            result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
            if (result)
            {
               //if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
               //{
                 // PartCloseSuccess = PartCloseTradeFunction();
                  //if (!PartCloseSuccess) SetAGlobalTicketVariable();
               //}//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
            }//if (result)
            if (!result)
            {
               err=GetLastError();
               if (ShowAlerts) Alert(OrderSymbol(), " sell trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err));
               Print(OrderSymbol(), " sell trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err));
            }//if (!result)
             
            return(0);
         }//if (Ask <= OrderOpenPrice() - (JumpingStopPips*Point))
      } // if (sl==0 || sl>OrderOpenPrice()
   
      // Decrement sl by sl - JumpingStopPips.
      // This will happen when market price <= (sl - JumpingStopPips)
      if (Bid<= sl - ((JumpingStopPips*2)*Point) && sl<= OrderOpenPrice())      
      {
         sl=sl-(JumpingStopPips*Point);
         result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
         if (result)
         {
            if (ShowAlerts==true) Alert("Jumping stop set at ",sl, " ", OrderSymbol(), " ticket no ", OrderTicket());
            Print("Jumping stop set: ", OrderSymbol(), ": SL ", sl, ": Ask ", Ask);
            //if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
            //{
              // PartCloseSuccess = PartCloseTradeFunction();
               //if (!PartCloseSuccess) SetAGlobalTicketVariable();
            //}//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
         }//if (result)          
         if (!result)
         {
            err=GetLastError();
            if (ShowAlerts) Alert(OrderSymbol(), " sell trade. Jumping stop function failed with error(",err,"): ",ErrorDescription(err));
            Print(OrderSymbol(), " sell trade. Jumping stop function failed with error(",err,"): ",ErrorDescription(err));
         }//if (!result)

      }// close if (Bid>= sl + (JumpingStopPips*Point) && sl>= OrderOpenPrice())         
   }//if (OrderType()==OP_SELL)

} //End of JumpingStopLoss sub


void TradeManagementModule()
{

   // Call the working subroutines one by one. 

   //Cut down 5 digit order modify calls for 5 digit crims, if required
   static int NoOfTicks = 9;
   int ndigits = MarketInfo(Symbol(), MODE_DIGITS);
   if (DoNotOverload5DigitCriminals && ( ndigits == 3 || ndigits == 5) )
   {
      NoOfTicks++;
   }//if (DoNotOverload5DigitCriminals && ( digits == 3 || digits == 5) )
   
   if (!DoNotOverload5DigitCriminals || ndigits == 2 || ndigits == 4)
   {
      NoOfTicks = 10;
   }//if (!DoNotOverload5DigitCriminals || digits == 2 || digits == 4)
   
   
   // Global variable to pick up on failed part-closes
   //if (GlobalVariablesTotal()>0) GlobalVariablesExist=true;
   //if (GlobalVariablesExist && GlobalVariablesTotal()>0) TryPartCloseAgain();
   //if (GlobalVariablesExist && GlobalVariablesTotal()==0) GlobalVariablesExist=false;
   
   if (NoOfTicks >= 10)
   {
      NoOfTicks = 0;//Reset the counter
      
      // Hidden stop loss
      //if (HideStopLossEnabled) HiddenStopLoss();
   
      // Hidden take profit
      //if (HideTakeProfitEnabled) HiddenTakeProfit();
   
      // Tighten the stop loss
      //if (UseTigheningStop) TightenStopLoss();
      
      // Breakeven
      if(BreakEven) BreakEvenStopLoss();
   
      // JumpingStop
      if(JumpingStop) JumpingStopLoss();
   
      // TrailingStop
      //if(TrailingStop) TrailingStopLoss();

   }//if (NoOfTicks >= 10)
   

}//void TradeManagementModule()


//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
//----

   ReadIndicatorValues();
   GetTradeDirection();

   //Check for potential trade cancellation
   if (TradeDirection != none)
   {
      IsDirectionStillValid();
   }//if (TradeDirection != none)

   
   ///////////////////////////////////////////////////////////////////////////////////////////////
   //Trade closure and management
   bool TradeExists;
   if (OrdersTotal() > 0) TradeExists = DoesTradeExist();
   
   if (TradeExists)
   {
      TradeManagementModule();
      TradeClosureModule();
      return;
   }//if (TradeExists)
   ///////////////////////////////////////////////////////////////////////////////////////////////
      

       
   ///////////////////////////////////////////////////////////////////////////////////////////////         
   //Trading
   if (TradingStatus == mode1buy) Mode1Buy();
   if (TradingStatus == mode1sell) Mode1Sell();
   if (TradingStatus == mode2buy) Mode2Buy();
   if (TradingStatus == mode2sell) Mode2Sell();
   if (TradingStatus == mode3buy) Mode3Buy();
   if (TradingStatus == mode3sell) Mode3Sell();
   if (TradingStatus == mode4buy) Mode4Buy();
   if (TradingStatus == mode4sell) Mode4Sell();
   
   ///////////////////////////////////////////////////////////////////////////////////////////////      
   
   DisplayUserFeedback();
   
//----
   return(0);
}
//+------------------------------------------------------------------+