//+------------------------------------------------------------------+
//|                             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  buy "Buy"
#define  sell "Sell"
#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  mode7buy "#7 Buy divergence"
#define  mode7sell "#7 Sell divergence"
#define  opentrade "There is a trade open"
#define  stopped "Trading is stopped"
#define  Manual_stopped "Manual_stopped"
#define  stopped_by_RecoveryL3 "stopped_by_RecoveryL3"
#define  stopped_by_HighSpread "stopped_by_HighSpread"
#define  stopped_by_HighVolatility "stopped_by_HighVolatility"
#define  MaxExposure_for_this_Currency "MaxExposure_for_this_Currency"  

//From iExposure
#define SYMBOLS_MAX 1024
#define DEALS          0
#define BUY_LOTS       1
#define BUY_PRICE      2
#define SELL_LOTS      3
#define SELL_PRICE     4
#define NET_LOTS       5
#define PROFIT         6

/*
this version is from Steve 19.8.2010 8.20 AM version
Revision history :
000   : Auto RentryLinePips
001   : Cosmetic enhancements
002   : high volatility protection (VolatilityStopTrading)
003   : high spread protection (SpreadStopTrading)
004   : change way for selecting Tp mode ect...
005   : Add MacdBB for trend dectection (not yet tested)
006   : Add Allow1, Allow2 ect
        Simple Recovery system, each level have it's own multiplier
007   : Bug correction
        RentryLine Pips is a multiplier of DailyATR

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
   - 7; #7 buy (divergence)
   - 7; #77 sell (divergence)
*/   
extern string  gen="----General inputs-------";
extern double  Lot               =0.4;
extern double  MaxLotsPerCurr    =1.6; // all modes merged
extern string  atms="----Trading methods----";
extern bool    Allow1            =true;
extern bool    Allow2            =true;
extern bool    Allow3            =true;
extern bool    Allow4            =true;
extern bool    Allow7            =true;
extern bool    CriminalIsECN     =true;
extern bool    StopTrading       =false;
extern int     MagicNumber       =444;
extern string  tpk ="----Recovery------------ ";
extern bool    UseRecovery          =true;
extern int     RecoveryRentry1Mult  =2;
extern int     RecoveryRentry2Mult  =4;
extern string  tpv ="ReEntryPips = DailyATR * mult ";
extern double  ReEntryPipsMult      =1;
extern string  tpi ="----TPMode 1=UseSixths--- ";
extern string  tpi2="--- 2=UseBol 3=UseAtr----";
extern int     TPMode               =1;
extern int     TakeProfit           =0;
extern int     AtrTpPeriod          =14;
extern int     AtrTpTimeFrame       =0;
extern double  AtrTpMultiplier      =3;
extern int     MinimumTargetinPips  =50;
extern string  htp="----Hidden TP settings------";
extern bool    HideTakeProfitEnabled=false;
extern int     HiddenTakeProfitPips =20;
extern string  sli="----SL for catastrophic events";
extern int     EmergencyStopLoss    =999;
extern string  six="----Sixths inputs-------------";
extern int     BarCount             =120;
extern bool    TradeZoneA           =false;
extern bool    TradeZoneB           =true;
extern string  tcm="----Trade closure module----";
extern bool    UseWhiteLineClosure  =true;
extern int     MinSeparationFromBlue=15;
extern string  tmm="----Trade management module----";
extern bool    DoNotOverload5DigitCriminals=true;
extern bool    BreakEven            =true;
extern int     BreakEvenPips        =25;
extern int     BreakEvenProfit      =10;
extern bool    HideBreakEvenStop    =false;
extern int     PipsAwayFromVisualBE =5;
extern string  JSL="----Jumping SL 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  TSL="----Trailing SL settings------";
extern bool    TrailingStop         =false;
extern int     TrailingStopPips     =50;
extern bool    HideTrailingStop     =false;
extern int     PipsAwayFromVisualTS =10;
extern bool    TrailAfterBreakevenOnly=false;
extern bool    StopTrailAtPipsProfit=false;
extern int     StopTrailPips        =0;
extern string  hsl1="----Hidden SL settings------";
extern bool    HideStopLossEnabled  =false;
extern int     HiddenStopLossPips   =20;
extern string  bl1="-------------------------------------------------------------";
extern string  tm1="TrendMode for #4---- 1=Rsi";
extern string  tm2="1=Atr 3=Adx 4=Lsma 5=StochsMacd";
extern string  tm3="6=MacdBB maxou mod";
extern int     TrendMode               =1;
extern string  rsin="----Rsi----";
extern int     RsiTf             =0;
extern int     RsiPeriod         =21;
extern string  atri="----Atr----";
extern int     AtrTf             =0;
extern int     AtrPeriod         =21;
extern int     DaysToLookBack    =10;
extern string  adxin="----Adx----";
extern int     AdxTf             =0;
extern int     AdxPeriod         =21;
extern string  ls="----LSMA----";
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    =00;
extern bool    ShowAlerts        =true;
extern color   ReEntryLineColour =Turquoise;

//-- 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";
string no7_BuyDivergence   = "#7 BUY_Div";
string no7_SelDivergence   = "#7 SELL_Div";

int            TicketNo, OpenTrades, SendMagicNumber;
double         LotSize;
double         BbUpper, BbLower;
double         BottomGoldLine;
double         BottomGreenLine;
double         MiddleWhiteLine;
double         TopGreenLine;
double         TopGoldLine;
double         StochWhite;
double         StochBlue;
double         MacdVal;
double         Ma1;
string         TradeDirection=none, TradingStatus=none;
int            OldBars;
double         TrendRsiVal, TrendAtrVal;
double         AdxVal, AdxPlusDI, AdxMinusDI;
string         RsiTrend, AtrTrend, AdxTrend, LsmaTrend, trend;
bool           RecoveryInProgress, TpMoved;
string         ExtSymbols[SYMBOLS_MAX];
int            ExtSymbolsTotal=0;
double         ExtSymbolsSummaries[SYMBOLS_MAX][7];
int            ExtLines=-1;
string         ExtCols[8]={"Symbol","Deals","Buy lots","Buy price","Sell lots","Sell price","Net lots","Profit"};
int            ExtShifts[8]={ 10, 80, 130, 180, 260, 310, 390, 460 };
int            ExtVertShift=14;
double         buy_price=0.0;
double         sell_price=0.0;
//OOOOOOOOOOOOOOOOOOOOOOOOOOO  Maxou Modif
double   DailyATR=0;         
int      multiplier;
int      MaxADr;
double   v_ActualSpread =0;
bool     RecoveryL3StopTrading   =false;
bool     SpreadStopTrading       =false;
bool     VolatilityStopTrading   =false;
int      ReEntryLinePips=200;
int      MacdBBTrend=0;
double   EURTotLots,GBPTotLots,CADTotLots,JPYTotLots,CHFTotLots,USDTotLots,AUDTotLots,NZDTotLots;
bool     MaxExposure=false;
//Misc
string         Gap, ScreenMessage, GvName;

void DisplayUserFeedback()//-------------------------------- 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, "DailyATR: ",DoubleToStr(DailyATR/multiplier, 1), " [",DoubleToStr(DailyATR, 0),"]", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "MaxAdr: ",DoubleToStr(MaxADr/multiplier, 1), " [",DoubleToStr(MaxADr, 0),"]", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Spread: ", DoubleToStr(v_ActualSpread/multiplier, 1)," [",DoubleToStr(v_ActualSpread, 1),"]", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "BreakEvenPips: ", DoubleToStr(BreakEvenPips/multiplier,0)," [",DoubleToStr(BreakEvenPips,0),"]", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "BreakEvenProfit: ", DoubleToStr(BreakEvenPips/multiplier,0)," [",DoubleToStr(BreakEvenProfit,0),"]", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "JumpingStopPips: ", DoubleToStr(JumpingStopPips/multiplier,0)," [",DoubleToStr(JumpingStopPips,0),"]", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "MinimumTargetinPips: ",DoubleToStr(MinimumTargetinPips/multiplier,0), " [",DoubleToStr(MinimumTargetinPips,0),"]", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "TrailingStopPips: ", DoubleToStr(TrailingStopPips/multiplier,0)," [",DoubleToStr(TrailingStopPips,0),"]", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "ReEntryLinePips: ", DoubleToStr(ReEntryLinePips/multiplier,0)," [",DoubleToStr(ReEntryLinePips,0),"]", 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, "Magic number: ", MagicNumber, NL);
   Comment(ScreenMessage);
}//void DisplayUserFeedback()


//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
//----
   if (StringSubstr(Symbol(), 0, 6) == "AUDCAD") { MagicNumber = MagicNumber+1 ; MaxADr=130;}// thats 1.3x normal daily ATR
   if (StringSubstr(Symbol(), 0, 6) == "AUDCHF") { MagicNumber = MagicNumber+2 ; MaxADr=190;}// the value is for 4 digit criminal
   if (StringSubstr(Symbol(), 0, 6) == "AUDJPY") { MagicNumber = MagicNumber+3 ; MaxADr=180;}
   if (StringSubstr(Symbol(), 0, 6) == "AUDNZD") { MagicNumber = MagicNumber+4 ; MaxADr=130;}
   if (StringSubstr(Symbol(), 0, 6) == "AUDUSD") { MagicNumber = MagicNumber+5 ; MaxADr=140;}
   if (StringSubstr(Symbol(), 0, 6) == "CADCHF") { MagicNumber = MagicNumber+6 ; MaxADr=190;}
   if (StringSubstr(Symbol(), 0, 6) == "CADJPY") { MagicNumber = MagicNumber+7 ; MaxADr=200;}
   if (StringSubstr(Symbol(), 0, 6) == "CHFJPY") { MagicNumber = MagicNumber+8 ; MaxADr=150;}
   if (StringSubstr(Symbol(), 0, 6) == "EURAUD") { MagicNumber = MagicNumber+9 ; MaxADr=200;}
   if (StringSubstr(Symbol(), 0, 6) == "EURCAD") { MagicNumber = MagicNumber+10; MaxADr=180;}
   if (StringSubstr(Symbol(), 0, 6) == "EURCHF") { MagicNumber = MagicNumber+11; MaxADr=170;}//??
   if (StringSubstr(Symbol(), 0, 6) == "EURGBP") { MagicNumber = MagicNumber+12; MaxADr=100;}
   if (StringSubstr(Symbol(), 0, 6) == "EURJPY") { MagicNumber = MagicNumber+13; MaxADr=200;} 
   if (StringSubstr(Symbol(), 0, 6) == "EURNZD") { MagicNumber = MagicNumber+14; MaxADr=270;}
   if (StringSubstr(Symbol(), 0, 6) == "EURUSD") { MagicNumber = MagicNumber+15; MaxADr=160;}
   if (StringSubstr(Symbol(), 0, 6) == "GBPCHF") { MagicNumber = MagicNumber+16; MaxADr=260;}
   if (StringSubstr(Symbol(), 0, 6) == "GBPJPY") { MagicNumber = MagicNumber+17; MaxADr=220;}
   if (StringSubstr(Symbol(), 0, 6) == "GBPUSD") { MagicNumber = MagicNumber+18; MaxADr=170;}
   if (StringSubstr(Symbol(), 0, 6) == "NZDJPY") { MagicNumber = MagicNumber+19; MaxADr=150;}
   if (StringSubstr(Symbol(), 0, 6) == "NZDUSD") { MagicNumber = MagicNumber+20; MaxADr=130;}
   if (StringSubstr(Symbol(), 0, 6) == "SGDJPY") { MagicNumber = MagicNumber+21; MaxADr=100;}
   if (StringSubstr(Symbol(), 0, 6) == "USDCHF") { MagicNumber = MagicNumber+22; MaxADr=150;}
   if (StringSubstr(Symbol(), 0, 6) == "USDCAD") { MagicNumber = MagicNumber+23; MaxADr=140;}
   if (StringSubstr(Symbol(), 0, 6) == "USDJPY") { MagicNumber = MagicNumber+24; MaxADr=120;}
   if (StringSubstr(Symbol(), 0, 6) == "USDNOK") { MagicNumber = MagicNumber+25; MaxADr=1100;}
   if (StringSubstr(Symbol(), 0, 6) == "USDSEK") { MagicNumber = MagicNumber+26; MaxADr=1200;}
   if (MagicNumber == 0) { MagicNumber = MagicNumber+27; }
   /*DisplayGapSize    =00;
   BreakEvenPips     =25;     //for H1=20 (H4=25) for M15=20
   BreakEvenProfit   =10;      //for H1=7  (H4=10) for M15=5
   JumpingStopPips   =50;     //for H1=35 (H4=50) for M15=25
   MinimumTargetinPips = 50;  //for H1=30 (H4=50) for M15=30
   AtrTpMultiplier   =3;      //for H1=2  (H4=3)  for M15=1
   TrailingStop      =true;   // (false)
   TrailingStopPips  =50;     //for H1=30 (H4=50) for M15=20*/
   Gap="";
   if (DisplayGapSize >0)
   {
      for (int cc=0; cc< DisplayGapSize; cc++)
      {
         Gap = StringConcatenate(Gap, " ");
      }   
   }//if (DisplayGapSize >0)
   
   if(Digits == 2 || Digits == 4) multiplier = 1;
   if(Digits == 3 || Digits == 5) multiplier = 10;
   if(Digits == 6) multiplier = 100;   
   if(Digits == 7) multiplier = 1000;   
   MaxADr*= multiplier;
   TakeProfit*= multiplier;
   EmergencyStopLoss*= multiplier;
   ReEntryLinePips*= multiplier;
   BreakEvenPips*= multiplier;
   BreakEvenProfit*= multiplier;
   PipsAwayFromVisualBE*= multiplier;
   JumpingStopPips*= multiplier;
   PipsAwayFromVisualJS*= multiplier;
   MinimumTargetinPips*= multiplier;
   TrailingStopPips*= multiplier;
   PipsAwayFromVisualTS*= multiplier;
   StopTrailPips*= multiplier;
   HiddenStopLossPips*= multiplier;
   HiddenTakeProfitPips*= 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 == 11) {  TradeDirection = down;  TradingStatus = mode1sell;}
   //Market needs to sink back within the bands
   if (dir == 2)  {  TradeDirection = up;    TradingStatus = mode2buy; }
   if (dir == 22) {  TradeDirection = down;  TradingStatus = mode2sell;}
   //Bulge
   if (dir == 3)  {  TradeDirection = up;    TradingStatus = mode3buy; }
   if (dir == 33) {  TradeDirection = down;  TradingStatus = mode3sell;}
   
   //Recovery
   CountOpenTrades();
   if (OpenTrades > 1) 
   {  RecoveryInProgress = true; TpMoved = false; }//if (OpenTrades > 1) 
   
   LotSize = Lot;
   SendMagicNumber = MagicNumber;
   //start();
   return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
   Comment("");
   return(0);
}
///////////////////////////////////////////////////////////////////////////////////////////
//TREND DETECTION MODULE

void GetRsiTrend() //------------------------------------- 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()//-------------------------------------- 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()//-------------------------------------- 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) 
   AdxTrend = down;//Trend is neither up nor ranging
}//End void GetAdxTrend()

double iLsma(int tf,int shift)//--------------------------- iLsma -----------------------------------------------------------------------------------
{
   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)//------------------- GetLsmaTrend -------------------------------------------------------------------------------------------
{
   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()//--------------------------------------- GetTheTrend-----------------------------------------------------------------------
{
   trend = "";
   string oldtrend = "";
   
   if (TrendMode==1)
   {
      GetRsiTrend();
      trend = RsiTrend;
      oldtrend = trend;
   }
   
   if (TrendMode==2)
   {
      GetAtrTrend();
      trend = AtrTrend;
      if (trend != oldtrend && oldtrend != "")
      {
         trend = confused;
         return;
      }//if (trend != oldtrend)
      oldtrend = trend;
   }
   
   if (TrendMode==3)
   {
      GetAdxTrend();
      trend = AdxTrend;
      if (trend != oldtrend && oldtrend != "")
      {
         trend = confused;
         return;
      }//if (trend != oldtrend)
      oldtrend = trend;
   }
   
   if (TrendMode==4)
   {
      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 (TrendMode==5)
   {
      GetStoch();
      MacdVal = GetStochMACD(FastEMA, SlowEMA, SignalSMA, StochasticPeriod , 0);
      if (StochBlue > MacdVal) { trend = up; }
      if (StochBlue < MacdVal) { trend = down; }
      oldtrend = trend;
   }
   
   if (TrendMode==6) 
   {
      double adblData[5];
      double MACDBB_Sig=0;  
      double MACDBB_HigB=0;  
      double MACDBB_LowB=0;  
      ArrayInitialize( adblData, 0.0 );
      calcMACD_BB(NULL, 0, 50, 250, 1, MODE_SMA, 20, 1.0, adblData, 0 );
      MACDBB_Sig  = adblData[4];
      //MACDBB_M15_MidB = adblData[1];
      MACDBB_HigB = adblData[2];
      MACDBB_LowB = adblData[3];
      if (MACDBB_Sig >MACDBB_HigB) {trend = up;  }
      if (MACDBB_Sig <MACDBB_LowB) {trend = down; }
      oldtrend = trend;
   }

}//End void GetTheTrend()


//END TREND DETECTION MODULE
///////////////////////////////////////////////////////////////////////////////////////////

void GetBB()//---------------------------------------------  GetBB -----------------------------------------------------------------
{
   BbUpper = iBands(NULL, 0, 25, 2, 0, PRICE_OPEN, MODE_UPPER, 0);
   BbLower = iBands(NULL, 0, 25, 2, 0, PRICE_OPEN, MODE_LOWER, 0);
}

bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take, int magic)//------ SendSingleTrade --------------------------------------------------------------------------------------------------------
{
   //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);
   //Recovery
   OpenTrades++;
   if (OpenTrades > 1)
   {
      TpMoved = false;
      RecoveryInProgress = true;
   }//if (OpenTrades > 1)
   return(true);
}

bool DoesTradeExist()//------------------------------------ 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() == SendMagicNumber && OrderSymbol() == Symbol() )      
      {
         TicketNo = OrderTicket();
         return(true);         
      }//if (OrderMagicNumber()==MagicNumber && OrderSymbol() == Symbol() )      
   }//for (int cc = OrdersTotal() - 1; cc >= 0 ; cc--)
   return(false);
}

bool CloseTrade()//----------------------------------------- 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);
}

double SetTarget(string tradedirection) //------------------ SetTarget --------------------------------------------------------------------------------------------
{
   double target = 0;
   if (tradedirection == sell) // SELL
   {
      if (TPMode==1) // use Sixths
      { 
         if ( MathAbs(Bid-TopGreenLine) < (Point*MinimumTargetinPips) ) { target = BottomGreenLine;  }
         else { target = TopGreenLine; }
      }
      if (TPMode==3) // use Atr
      {
         double AtrVal = iATR(Symbol(), AtrTpTimeFrame, AtrTpPeriod, 0) * AtrTpMultiplier;
         target = NormalizeDouble(Bid - AtrVal,Digits);
      } 
      if (TPMode==2) // use BollingerBands middle band
      {
         double MiddleBB = iBands(NULL, 0,  25, 2, 0, PRICE_CLOSE, MODE_MAIN, 0);
         if ( MathAbs(Bid-MiddleBB) < (Point*MinimumTargetinPips) ) 
         { target = Bid - (MinimumTargetinPips * Point); }
         else { target = MiddleBB; } 
      }
   }
   else if (tradedirection == buy) // BUY
   {
      if (TPMode==1) // use Sixths
      {
         if ( MathAbs(Ask-TopGreenLine) < (Point*MinimumTargetinPips) ) { target = TopGreenLine;  }
         else { target = TopGreenLine; }
      }
      if (TPMode==3) // use Atr
      {
         AtrVal = iATR(Symbol(), AtrTpTimeFrame, AtrTpPeriod, 0) * AtrTpMultiplier;
         target = NormalizeDouble(Ask + AtrVal,Digits);
      } 
      if (TPMode==2) // use BollingerBands middle band
      {
         MiddleBB = iBands(NULL, 0,  25, 2, 0, PRICE_CLOSE, MODE_MAIN, 0);
         if ( MathAbs(Ask-MiddleBB) < (Point*MinimumTargetinPips) ) 
         { target = Ask + (MinimumTargetinPips * Point); }
         else { target = MiddleBB; }
      }
   }
   return (NormalizeDouble(target,Digits));
}

void Buy(string comment)//-------------------------------- Buy ------------------------------------------------------------------------------
{
   if (DoesTradeExist()) return;
   if (ObjectFind("Re entry line") > -1) ObjectDelete("Re entry line");
   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 (take == 0) // if no fixed take profit, check use options for calculating take profit
   { take = SetTarget(buy);}
   
   bool result = SendSingleTrade(OP_BUY, comment, LotSize, Ask, stop, take, SendMagicNumber);
   if (result) 
   {
      GlobalVariableSet(GvName, 0);
      TradingStatus = opentrade;
      AddReEntryLine(OP_BUY);
   }//if (result)
}

void Sell(string comment)//------------------------------- Sell -------------------------------------------------------------------------------
{
   if (DoesTradeExist()) return;
   if (ObjectFind("Re entry line") > -1) ObjectDelete("Re entry line");
   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 (take == 0) // if no fixed take profit, check use options for calculating take profit
   { take = SetTarget(sell);}

   bool result = SendSingleTrade(OP_SELL, comment, LotSize, Bid, stop, take, SendMagicNumber);
   if (result) 
   {
      GlobalVariableSet(GvName, 0);
      TradingStatus = opentrade;
      AddReEntryLine(OP_SELL);
   }//if (result)
}

void GetSixths()//---------------------------------------- GetSixths ----------------------------------------------------------------------
{
   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);
}

void GetStoch()//----------------------------------------- GetStoch ---------------------------------------------------------------------
{
   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);
}

double GetStochMACD(int fast_ema_period, int slow_ema_period, int signal_period, int StochasticPeriod, int shift)//---- GetStochMACD ----------------------------------------------------------------------------------------------------------
{
  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); 
}
void GetMA()//--------------------------------------------- GetMA -----------------------------------------------------------------
{
   Ma1 = iMA(NULL, 0, 1, 0, MODE_SMA, PRICE_CLOSE, 0);
}

void ReadIndicatorValues()//------------------------------- ReadIndicatorValues -------------------------------------------------------------------------------
{
   GetBB();//Bollinger Bands
   GetSixths();
   GetStoch();
   MacdVal = GetStochMACD(FastEMA, SlowEMA, SignalSMA, StochasticPeriod , 0);
   GetMA();
}

void GetTradeDirection()//------------------------------- 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.
   */
   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 ((1-BbSeparation) < MinSepFromBB) TradeDirection = none;
      if (TradeDirection == down)
      {
         if (Ask < BbUpper)//============#1
         {  TradingStatus = mode1sell;       GlobalVariableSet(GvName, 11);   }
         if (Ask >= BbUpper)//===========#2
         {  TradingStatus = mode2sell;       GlobalVariableSet(GvName, 22);   }
         double screentop = WindowPriceMax(0);//====#3   
         if (BbUpper >= screentop) 
         {  TradingStatus = mode3sell;       GlobalVariableSet(GvName, 33);   }
         
         GetTheTrend();//===========#4
         if (trend == ranging)
         {  TradingStatus = mode4sell;       GlobalVariableSet(GvName, 44);   }
         if (Ask > target && OldBars != Bars)//==========#7
         {
            OldBars = Bars;
            double BearVal = iCustom(NULL, 0, "FX5 MACD DIVERGENCE V1.0", " ", 12, 26, 9, " ", false, false, false, 1, 1);
            if (BearVal != EMPTY_VALUE)
            {  TradingStatus = mode7sell;    GlobalVariableSet(GvName, 77);   }  
         }//if (Ask > Target)
         
      }//if (TradeDirection == down)
   }//if (Ask > target)

   if (TradeZoneA) target = BottomGoldLine;
   if (TradeZoneB) target = BottomGreenLine;

   //Check for long 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 (BbSeparation < MinSepFromBB) TradeDirection = none;
      
      if (TradeDirection == up)
      {
         //#1
         if (Bid > BbLower)
         {  TradingStatus = mode1buy;  GlobalVariableSet(GvName, 1);  }
         //#2
         if (Bid <= BbLower)
         {  TradingStatus = mode2buy;  GlobalVariableSet(GvName, 2);  }
         //#3
         double screenbottom = WindowPriceMin(0);   
         if (BbLower <= screenbottom) 
         {  TradingStatus = mode3buy;  GlobalVariableSet(GvName, 3);  } 
         //#4
         GetTheTrend();
         if (trend == ranging)
         {  TradingStatus = mode4buy;  GlobalVariableSet(GvName, 4);  }
         //#7
         if (Bid < target && OldBars != Bars)
         {
            OldBars = Bars;
            double BullVal = iCustom(NULL, 0, "FX5 MACD DIVERGENCE V1.0", " ", 12, 26, 9, " ", false, false, false, 0, 1);
            if (BullVal != EMPTY_VALUE)
            {  TradingStatus = mode7buy;  GlobalVariableSet(GvName, 7);  }  
         }
      }//if (TradeDirection == up)
   }//if (Bid < target)
}

void IsDirectionStillValid()//---------------------------- IsDirectionStillValid ----------------------------------------------------------------------------------
{
   if (Ask <= TopGreenLine && Ask >= BottomGreenLine && Bid <= TopGreenLine && Bid >= BottomGreenLine)
   {
      TradeDirection = none;
      TradingStatus = none;
      GlobalVariableSet(GvName, 0);
   }
   /*if (DailyATR>=MaxADr) // PROTECTION  Maxou modif
   {
      TradeDirection = none;
      TradingStatus = none;
      GlobalVariableSet(GvName, 0);
   }*/
}

void AddReEntryLine(int type)//---------------------------- AddReEntryLine ----------------------------------------------------------------------------------
{
      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)
}

bool WhiteLineClose(int type)//----------------------------- WhiteLineClose ---------------------------------------------------------------------------------
{
   if (OrderProfit() < 0) return(false);
   if (type == OP_BUY)
   { if (StochWhite > 85 && StochWhite - StochBlue > MinSeparationFromBlue) return(true); }
   if (type == OP_SELL)
   { if (StochWhite < 15 && StochBlue - StochWhite > MinSeparationFromBlue) return(true); }

   return(false);
}

void TradeClosureModule()//--------------------------------- TradeClosureModule -----------------------------------------------------------------------------
{
   bool CloseRequired = false;
   //White line closure
   if (!CloseRequired)
   {
      if (UseWhiteLineClosure)
      {  CloseRequired = WhiteLineClose(OrderType() );  }
   }//if (!CloseRequired)
   if (CloseRequired) CloseTrade();
}

////////////////////////////////////////////////////////////////////////////////////////////////
//TRADE MANAGEMENT MODULE

bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop )//------- CheckForHiddenStopLossHit -------------------------------------------------------------------------------------------------------
{
   //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)
}

void BreakEvenStopLoss() //--------------------------------- 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 (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)      
            }    
         }
}

void JumpingStopLoss() //---------------------------------- 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 (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 (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 (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 (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)

}

void HiddenStopLoss()//---------------------------------- HiddenStopLoss ----------------------------------------------------------------------------
{
   //Called from ManageTrade if HideStopLossEnabled = true
   //Should the order close because the stop has been passed?
   //Buy trade
   if (OrderType() == OP_BUY)
   {
      double sl = NormalizeDouble(OrderOpenPrice() - (HiddenStopLossPips * Point), Digits);
      if (Bid <= sl)
      {
         bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         { if (ShowAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());  }
         else
         {
            int err=GetLastError();
            if (ShowAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (Bid <= sl)      
   }//if (OrderType() == OP_BUY)
   
   //Sell trade
   if (OrderType() == OP_SELL)
   {
      sl = NormalizeDouble(OrderOpenPrice() + (HiddenStopLossPips * Point), Digits);
      if (Ask >= sl)
      {
         result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {  if (ShowAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()); }//if (result)
         else
         {
            err=GetLastError();
            if (ShowAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (Ask >= sl)   
   }//if (OrderType() == OP_SELL)
   

}

void HiddenTakeProfit()//-------------------------------- HiddenTakeProfit ------------------------------------------------------------------------------
{
   //Called from ManageTrade if HideStopLossEnabled = true
   //Should the order close because the stop has been passed?
   if (OrderType() == OP_BUY)
   {
      double tp = NormalizeDouble(OrderOpenPrice() + (HiddenTakeProfitPips * Point), Digits);
      if (Bid >= tp)
      {
         bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         { if (ShowAlerts==true) Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()); }
         else
         {
            int err=GetLastError();
            if (ShowAlerts==true) Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (Ask >= tp)      
   }//if (OrderType() == OP_BUY)
   
   if (OrderType() == OP_SELL)
   {
      tp = NormalizeDouble(OrderOpenPrice() - (HiddenTakeProfitPips * Point), Digits);
      if (Ask <= tp)
      {
         result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {  if (ShowAlerts==true) Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()); }
         else
         {
            err=GetLastError();
            if (ShowAlerts==true) Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (Bid <= tp)   
   }//if (OrderType() == OP_SELL)
}

void TrailingStopLoss()//------------------------------ TrailingStopLoss --------------------------------------------------------------------------------
{
      if (TrailAfterBreakevenOnly && OrderType()==OP_BUY)  {if(OrderStopLoss()<OrderOpenPrice()) return(0);}
      if (TrailAfterBreakevenOnly && OrderType()==OP_SELL) {if(OrderStopLoss()>OrderOpenPrice()) return(0);}
   bool result;
   double sl=OrderStopLoss(); //Stop loss
   double BuyStop=0, SellStop=0;
   
   if (OrderType()==OP_BUY) 
      {
         if (HideTrailingStop)
         {
            bool TradeClosed = CheckForHiddenStopLossHit(OP_BUY, PipsAwayFromVisualTS, OrderStopLoss() );
            if (TradeClosed) return;//Trade has closed, so nothing else to do
         }//if (HideJumpingStop)
		   
		   if (Bid >= OrderOpenPrice() + (TrailingStopPips*Point))
		   {
		       if (OrderStopLoss() == 0) sl = OrderOpenPrice();
		       if (Bid > sl +  (TrailingStopPips*Point))
		       {
		          sl= Bid - (TrailingStopPips*Point);
		          // Exit routine if user has chosen StopTrailAtPipsProfit and
		          // sl is past the profit Point already
		          if (StopTrailAtPipsProfit && sl>= OrderOpenPrice() + (StopTrailPips*Point)) return;
		          result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
               if (result) {Print("Trailing stop updated: ", OrderSymbol(), ": SL ", sl, ": Ask ", Ask);}
               else {int err=GetLastError(); Print(OrderSymbol(), " order modify failed with error(",err,"): ",ErrorDescription(err)); }
		       }//if (Bid > sl +  (TrailingStopPips*Point))
		   }//if (Bid >= OrderOpenPrice() + (TrailingStopPips*Point))
      }//if (OrderType()==OP_BUY) 

      if (OrderType()==OP_SELL) 
      {
		   if (Ask <= OrderOpenPrice() - (TrailingStopPips*Point))
		   {
             if (HideTrailingStop)
             {
                TradeClosed = CheckForHiddenStopLossHit(OP_SELL, PipsAwayFromVisualTS, OrderStopLoss() );
                if (TradeClosed) return;//Trade has closed, so nothing else to do
             }//if (HideJumpingStop)
		   
		       if (OrderStopLoss() == 0) sl = OrderOpenPrice();
		       if (Ask < sl -  (TrailingStopPips*Point))
		       {
	               sl= Ask + (TrailingStopPips*Point);
  	               // Exit routine if user has chosen StopTrailAtPipsProfit and
		            // sl is past the profit Point already
		            if (StopTrailAtPipsProfit && sl<= OrderOpenPrice() - (StopTrailPips*Point)) return;
		            result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
                  if (result)
                  { Print("Trailing stop updated: ", OrderSymbol(), ": SL ", sl, ": Bid ", Bid);}
                  else {err=GetLastError(); Print(OrderSymbol(), " order modify failed with error(",err,"): ",ErrorDescription(err));}
		       }//if (Ask < sl -  (TrailingStopPips*Point))
		   }//if (Ask <= OrderOpenPrice() - (TrailingStopPips*Point))
      }//if (OrderType()==OP_SELL) 
}


void TradeManagementModule()//--------------------------- 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)
   
   if (NoOfTicks >= 10)
   {
      NoOfTicks = 0;//Reset the counter
      if (HideStopLossEnabled) HiddenStopLoss();// Hidden stop loss
      if (HideTakeProfitEnabled) HiddenTakeProfit();// Hidden take profit
      if(BreakEven) BreakEvenStopLoss();// Breakeven
      if(JumpingStop) JumpingStopLoss();// JumpingStop
      if(TrailingStop) TrailingStopLoss();//TrailingStop
   }//if (NoOfTicks >= 10)
}
//END TRADE MANAGEMENT MODULE
////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////
// RECOVERY MODULE
void RecoveryModule()//----------------------------------- RecoveryModule ---------------------------------------------------------------------------
{
   //Check that recovery is necessary
   if (OrderType() == OP_BUY)
   {if (Ask > OrderOpenPrice() - (ReEntryLinePips * Point) ) return;}
   if (OrderType() == OP_SELL)
   {if (Bid < OrderOpenPrice() + (ReEntryLinePips * Point) ) return;}
   RecoveryL3StopTrading = false;
   //Count no of open trades. The final one in the sequence will be the one that needs recovery
   CountOpenTrades();
   //If 1 trade open, then recovery is at the 2 stage
   if (OpenTrades == 1)
   {  SendMagicNumber = MagicNumber + 30;     LotSize = Lot * RecoveryRentry1Mult;  }
   //If 2 trades open, then recovery is at the 4 stage
   if (OpenTrades == 2)
   {  SendMagicNumber = MagicNumber + 60;    LotSize = Lot * RecoveryRentry2Mult;   }
   //Stop trading if the full 3-trade position is open
   if (OpenTrades == 3)
   {  RecoveryL3StopTrading = true; }
   
   RecoveryInProgress = true;
}

void CountOpenTrades()//---------------------------------- CountOpenTrades ----------------------------------------------------------------------------
{
   OpenTrades = 0;
   for (int cc = 0; cc < OrdersTotal(); cc++)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderSymbol() == Symbol() )
      {OpenTrades++;}
   }//for (int cc = 0; cc < OrdersTotal() - 1; cc++)
}

void ModifyTakeProfit(double NewTake)//-------------------- ModifyTakeProfit ------------------------------------------------------------------------------------------
{
   TpMoved = true;
   for (int cc = OrdersTotal() -1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderTakeProfit() != NewTake)
      {
         TicketNo = OrderTicket();
         bool result = OrderModify(TicketNo, OrderOpenPrice(), OrderStopLoss(), NewTake, OrderExpiration(), CLR_NONE);
         if (!result) TpMoved = false;
      }//if (OrderTakeProfit() != NewTake)
   }//for (int cc = OrdersTotal() -1; cc >= 0; cc--)
}

void CheckRecoveryTakeProfit()//---------------------------- CheckRecoveryTakeProfit ----------------------------------------------------------------------------------
{
   ExtLines = 0;
   int    i,col,line;
   ArrayInitialize(ExtSymbolsSummaries,0.0);
   int total=Analyze();
   if(total>0)
   {
      line=0;
      for(i=0; i<ExtSymbolsTotal; i++)
      {
         if (ExtSymbols[i] != Symbol() ) continue;
         if(ExtSymbolsSummaries[i][DEALS]<=0) continue;
         line++;
         //---- add line
         if(line>ExtLines)
         {
            int y_dist=ExtVertShift*(line+1)+1;
            ExtLines++;
         }//if(line>ExtLines)
         //---- set line
         //color  price_colour;//Steve mod
         int    digits=MarketInfo(ExtSymbols[i],MODE_DIGITS);
         double buy_lots=ExtSymbolsSummaries[i][BUY_LOTS];
         double sell_lots=ExtSymbolsSummaries[i][SELL_LOTS];
         if(buy_lots!=0)  buy_price=NormalizeDouble(ExtSymbolsSummaries[i][BUY_PRICE]/buy_lots, Digits);
         if(sell_lots!=0) sell_price=NormalizeDouble(ExtSymbolsSummaries[i][SELL_PRICE]/sell_lots, Digits);
      }//for(i=0; i<ExtSymbolsTotal; i++)
   }//if(total>0)
}

int Analyze()//------------------------------------------ Analyze --------------------------------------------------------------------
{
   double profit;
   int    i,index,type,total=OrdersTotal();
//----
   for(i=0; i<total; i++)
     {
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
      type=OrderType();
      if(type!=OP_BUY && type!=OP_SELL) continue;
      index=SymbolsIndex(OrderSymbol());
      if(index<0 || index>=SYMBOLS_MAX) continue;
      //----
      ExtSymbolsSummaries[index][DEALS]++;
      profit=OrderProfit()+OrderCommission()+OrderSwap();
      ExtSymbolsSummaries[index][PROFIT]+=profit;
      if(type==OP_BUY)
        {
         ExtSymbolsSummaries[index][BUY_LOTS]+=OrderLots();
         ExtSymbolsSummaries[index][BUY_PRICE]+=OrderOpenPrice()*OrderLots();
        }
      else
        {
         ExtSymbolsSummaries[index][SELL_LOTS]+=OrderLots();
         ExtSymbolsSummaries[index][SELL_PRICE]+=OrderOpenPrice()*OrderLots();
        }
     }
//----
   total=0;
   for(i=0; i<ExtSymbolsTotal; i++)
     {
      if(ExtSymbolsSummaries[i][DEALS]>0) total++;
     }
//----
   return(total);
}//int Analyze()

int SymbolsIndex(string SymbolName)//-------------------- SymbolsIndex ------------------------------------------------------------------------------------------
{
   bool found=false;
//----
   for(int i=0; i<ExtSymbolsTotal; i++)
     {
      if(SymbolName==ExtSymbols[i])
        {
         found=true;
         break;
        }
     }
//----
   if(found) return(i);
   if(ExtSymbolsTotal>=SYMBOLS_MAX) return(-1);
//----
   i=ExtSymbolsTotal;
   ExtSymbolsTotal++;
   ExtSymbols[i]=SymbolName;
   ExtSymbolsSummaries[i][DEALS]=0;
   ExtSymbolsSummaries[i][BUY_LOTS]=0;
   ExtSymbolsSummaries[i][BUY_PRICE]=0;
   ExtSymbolsSummaries[i][SELL_LOTS]=0;
   ExtSymbolsSummaries[i][SELL_PRICE]=0;
   ExtSymbolsSummaries[i][NET_LOTS]=0;
   ExtSymbolsSummaries[i][PROFIT]=0;
//----
   return(i);
}
//END  RECOVERY MODULE
////////////////////////////////////////////////////////////////////////////////////////////////


void Mode1Buy()//--------------------------------- TRADING MODULE -----------------------------------------------------------------------------
{
   if (DoesTradeExist()) return;
   RefreshRates();
   if (Bid < BbLower) { Buy(no1_Buy25); } 
}
void Mode1Sell()
{
   if (DoesTradeExist()) return;
   RefreshRates();
   if (Ask > BbUpper) { Sell(no1_Sel25); }
}
void Mode2Buy()
{
   //Equates to #1 Buy 1 MA 25 BB
   if (DoesTradeExist()) return;
   RefreshRates();
   double  Var1, Var2;
   Var1 = iMA(NULL, PERIOD_H4,  1, 0, MODE_LWMA, PRICE_MEDIAN,  0);
   BbLower = iBands(NULL, PERIOD_H4,  25, 2, 0, PRICE_CLOSE, MODE_LOWER, 0); 
   RefreshRates();
   if (Var1 > BbLower) { Buy(no2_Buy1MA); }
}
void Mode2Sell()
{
   if (DoesTradeExist()) return;
   RefreshRates();
   double  Var1, Var2;
   Var1 = iMA(NULL, PERIOD_H4,  1, 0, MODE_LWMA, PRICE_MEDIAN,  0);
   BbUpper = iBands(NULL, PERIOD_H4,  25, 2, 0, PRICE_CLOSE, MODE_UPPER, 0);
   RefreshRates();
   if( Var1 < BbUpper) { Sell(no2_Sel1MA); }
}
void Mode3Buy()
{
   if (DoesTradeExist()) return;
   double  Var1, Var2, Var3;
   Var1 = iMA(NULL, PERIOD_H4, 1, 0, MODE_LWMA, PRICE_MEDIAN,  0);
   Var2 = iMA(NULL, PERIOD_H4, 4, 0, MODE_LWMA, PRICE_LOW,  0);
   BbLower = iBands(NULL, PERIOD_H4,  25, 2, 0, PRICE_CLOSE, MODE_LOWER, 0); 
   RefreshRates();
   if(Bid < Var2 && Var1 > BbLower) { Buy(no3_BuyBulge); }    
}
void Mode3Sell()
{
   if (DoesTradeExist()) return;
   double  Var1, Var2, Var3;
   Var1 = iMA(NULL, PERIOD_H4, 1, 0, MODE_LWMA, PRICE_MEDIAN,  0);
   Var3 = iMA(NULL, PERIOD_H4, 4, 0, MODE_LWMA, PRICE_HIGH,  0);
   BbUpper = iBands(NULL, PERIOD_H4,  25, 2, 0, PRICE_CLOSE, MODE_UPPER, 0);
   RefreshRates();
   if(Bid  > Var3 && Var1 < BbUpper) { Sell(no3_SelBulge); }
}
void Mode4Buy()
{
   if (DoesTradeExist()) return;
   BbLower = iBands(NULL, PERIOD_H4,  25, 2, 0, PRICE_CLOSE, MODE_LOWER, 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)) { Buy(no4_BuyBB13); }
}
void Mode4Sell()
{
   if (DoesTradeExist()) return;
   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)) { Sell(no4_SelBB13); }
}
void Mode7Buy()
{
   if (DoesTradeExist()) return;
   double  Var1, Var2;
   Var1 = iMA(NULL, PERIOD_H4, 1, 0, MODE_LWMA, PRICE_MEDIAN, 1);
   Var2 = iBands(NULL, PERIOD_H4,  25, 2, 3, PRICE_CLOSE, MODE_LOWER, 1); 
   BbLower = iBands(NULL, PERIOD_H4,  25, 2, 3, PRICE_CLOSE, MODE_LOWER, 0); 
   RefreshRates();
   if (Bid > BbLower && Var1 < Var2) 
   { Buy(no7_BuyDivergence);} 
}
void Mode7Sell()
{
   if (DoesTradeExist()) return;
   double  Var1, Var2;
   Var1 = iMA(NULL, PERIOD_H4, 1, 0, MODE_LWMA, PRICE_MEDIAN, 1);
   Var2 = iBands(NULL, PERIOD_H4,  25, 2, 3, PRICE_CLOSE, MODE_LOWER, 1); 
   BbUpper = iBands(NULL, PERIOD_H4,  25, 2, 3, PRICE_CLOSE, MODE_UPPER, 0);
   RefreshRates();
   if( Bid < BbUpper && Var1 > Var2)
   {  Sell(no7_SelDivergence);}
}

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
//OOOOOOOOOOOOOOOOOOOOOOOOOOO  Maxou Modif
   DailyATR = iATR(Symbol(), PERIOD_D1, 14, 0) ; // in 4 digits
   if(Digits == 5 ) DailyATR = DailyATR*100000;
   if(Digits == 4 ) DailyATR = DailyATR*10000;
   if(Digits == 3 ) DailyATR = DailyATR*1000;
   if(Digits == 2 ) DailyATR = DailyATR*100;
   if (Period()== PERIOD_H4)
   {
      BreakEvenPips      =NormalizeDouble(DailyATR/6,0);  if (BreakEvenPips<15*multiplier)        BreakEvenPips=15*multiplier;      
      BreakEvenProfit    =NormalizeDouble(DailyATR/15,0); if (BreakEvenProfit<5*multiplier)       BreakEvenProfit=5*multiplier;    
      JumpingStopPips    =NormalizeDouble(DailyATR/3,0);  if (JumpingStopPips<20*multiplier)      JumpingStopPips=20*multiplier;    
      MinimumTargetinPips=NormalizeDouble(DailyATR/3,0);  if (MinimumTargetinPips<20*multiplier)  MinimumTargetinPips=20*multiplier;
      AtrTpMultiplier    =3;      
      TrailingStop       =true;   
      TrailingStopPips   =NormalizeDouble(DailyATR/3,0);  if (TrailingStopPips<20*multiplier)     TrailingStopPips=20*multiplier;     
   }
   if (Period()== PERIOD_H1)
   {
      BreakEvenPips      =NormalizeDouble(DailyATR/8,0);  if (BreakEvenPips<12*multiplier)        BreakEvenPips=12*multiplier;      
      BreakEvenProfit    =NormalizeDouble(DailyATR/15,0); if (BreakEvenProfit<5*multiplier)       BreakEvenProfit=5*multiplier;     
      JumpingStopPips    =NormalizeDouble(DailyATR/5,0);  if (JumpingStopPips<15*multiplier)      JumpingStopPips=15*multiplier;    
      MinimumTargetinPips=NormalizeDouble(DailyATR/5,0);  if (MinimumTargetinPips<15*multiplier)  MinimumTargetinPips=15*multiplier;
      AtrTpMultiplier    =2.5;      
      TrailingStop       =true;   
      TrailingStopPips   =NormalizeDouble(DailyATR/5,0);  if (TrailingStopPips<15*multiplier)     TrailingStopPips=15*multiplier;     
   }
   if (Period()== PERIOD_M15)
   {
      BreakEvenPips      =NormalizeDouble(DailyATR/10,0);  if (BreakEvenPips<10*multiplier)       BreakEvenPips=10*multiplier;     
      BreakEvenProfit    =NormalizeDouble(DailyATR/15,0); if (BreakEvenProfit<5*multiplier)       BreakEvenProfit=5*multiplier;     
      JumpingStopPips    =NormalizeDouble(DailyATR/7,0);  if (JumpingStopPips<12*multiplier)      JumpingStopPips=12*multiplier;   
      MinimumTargetinPips=NormalizeDouble(DailyATR/7,0);  if (MinimumTargetinPips<12*multiplier)  MinimumTargetinPips=12*multiplier;
      AtrTpMultiplier    =2;      
      TrailingStop       =true;  
      TrailingStopPips   =NormalizeDouble(DailyATR/7,0);  if (TrailingStopPips<12*multiplier) TrailingStopPips=12*multiplier;     
   }

   ReEntryLinePips   =NormalizeDouble(DailyATR*ReEntryPipsMult,0);  if (ReEntryLinePips<50*multiplier) ReEntryLinePips=50*multiplier;     
   /*ReEntryLinePips*= multiplier;
   BreakEvenPips*= multiplier;
   BreakEvenProfit*= multiplier;
   JumpingStopPips*= multiplier;
   MinimumTargetinPips*= multiplier;
   TrailingStopPips*= multiplier;*/

   // ---------------------------------- spread protection
   v_ActualSpread = MarketInfo(Symbol(), MODE_SPREAD);
   if (v_ActualSpread>DailyATR/15)   SpreadStopTrading=true; else SpreadStopTrading=false;

   // ---------------------------------- volatility protection
   if (DailyATR>=MaxADr) VolatilityStopTrading=true; else VolatilityStopTrading=false;

   //------------------------------------ MaxLotsPerCurrency                                                  =
   MaxExposure=false;
   if (  StringSubstr(Symbol(), 0, 3)=="EUR" || StringSubstr(Symbol(), 3, 3)=="EUR")
   {  EURTotLots  = TotalCurrLOT("EUR");
      if (EURTotLots>=MaxLotsPerCurr) MaxExposure=true;
   }
   if (  StringSubstr(Symbol(), 0, 3)=="GBP" || StringSubstr(Symbol(), 3, 3)=="GBP")
   {  GBPTotLots  = TotalCurrLOT("GBP");
      if (GBPTotLots>=MaxLotsPerCurr) MaxExposure=true;
   }
   if (  StringSubstr(Symbol(), 0, 3)=="CAD" || StringSubstr(Symbol(), 3, 3)=="CAD")
   {  CADTotLots  = TotalCurrLOT("CAD");
      if (CADTotLots>=MaxLotsPerCurr) MaxExposure=true;
   }
   if (  StringSubstr(Symbol(), 0, 3)=="JPY" || StringSubstr(Symbol(), 3, 3)=="JPY")
   {  JPYTotLots  = TotalCurrLOT("JPY");
      if (JPYTotLots>=MaxLotsPerCurr) MaxExposure=true;
   }
   if (  StringSubstr(Symbol(), 0, 3)=="CHF" || StringSubstr(Symbol(), 3, 3)=="CHF")
   {  CHFTotLots  = TotalCurrLOT("CHF");
      if (CHFTotLots>=MaxLotsPerCurr) MaxExposure=true;
   }
   if (  StringSubstr(Symbol(), 0, 3)=="USD" || StringSubstr(Symbol(), 3, 3)=="USD")
   {  USDTotLots  = TotalCurrLOT("USD");
      if (USDTotLots>=MaxLotsPerCurr) MaxExposure=true;
   }
   if (  StringSubstr(Symbol(), 0, 3)=="AUD" || StringSubstr(Symbol(), 3, 3)=="AUD")
   {  AUDTotLots  = TotalCurrLOT("AUD");
      if (AUDTotLots>=MaxLotsPerCurr) MaxExposure=true;
   }
   if (  StringSubstr(Symbol(), 0, 3)=="NZD" || StringSubstr(Symbol(), 3, 3)=="NZD")
   {  NZDTotLots  = TotalCurrLOT("NZD");
      if (NZDTotLots>=MaxLotsPerCurr) MaxExposure=true;
   }

//OOOOOOOOOOOOOOOOOOOOOOOOOOO  END Maxou Modif

   bool TradeExists;
   OpenTrades = 0;
   
   //Recovery   
   if (OrdersTotal() > 0) CountOpenTrades();
   if (OpenTrades > 1) RecoveryInProgress = true;
   if (OpenTrades == 0) 
   {
      RecoveryInProgress = false;
      TpMoved = true;
      LotSize = Lot;
      SendMagicNumber = MagicNumber;
   }//if (OpenTrades == 0) 
   
   if (RecoveryInProgress && !TpMoved)
   {
      //TradeExists = DoesTradeExist();//Identifies and selects the most recent trade
      CheckRecoveryTakeProfit();
      if (buy_price > 0) ModifyTakeProfit(buy_price);
      if (sell_price > 0) ModifyTakeProfit(sell_price);      
   }//if (RecoveryInProgress)
   
   ReadIndicatorValues();
   GetTradeDirection();

   //Check for potential trade cancellation
   if (TradeDirection != none  )
   {
      IsDirectionStillValid();
   }//if (TradeDirection != none)
   
   ///////////////////////////////////////////////////////////////////////////////////////////////
   //Trade closure and management
   if (OrdersTotal() > 0) TradeExists = DoesTradeExist();
   if (TradeExists)
   {
      if (OrderProfit() < 0 && UseRecovery) 
      {  RecoveryModule();}
      
      if (OpenTrades == 1)
      {
         TradeManagementModule();
         TradeClosureModule();
      }//if (!RecoveryInProgress)
   }//if (TradeExists)
   ///////////////////////////////////////////////////////////////////////////////////////////////
       
   ///////////////////////////////////////////////////////////////////////////////////////////////         
   //Trading
   if (StopTrading || RecoveryL3StopTrading || SpreadStopTrading || VolatilityStopTrading || MaxExposure)
   {
      TradeDirection = none;
      TradingStatus = stopped;
      if (StopTrading)TradingStatus = Manual_stopped;
      if (RecoveryL3StopTrading)TradingStatus = stopped_by_RecoveryL3;
      if (SpreadStopTrading)TradingStatus = stopped_by_HighSpread;
      if (VolatilityStopTrading)TradingStatus = stopped_by_HighVolatility;
      if (MaxExposure)TradingStatus = MaxExposure_for_this_Currency;
      GlobalVariableDel(GvName);
      DisplayUserFeedback();
      return;
   }//if (StopTrading)
   if (TradingStatus == mode1buy  && Allow1) Mode1Buy();
   if (TradingStatus == mode1sell && Allow1) Mode1Sell();
   if (TradingStatus == mode2buy  && Allow2) Mode2Buy();
   if (TradingStatus == mode2sell && Allow2) Mode2Sell();
   if (TradingStatus == mode3buy  && Allow3) Mode3Buy();
   if (TradingStatus == mode3sell && Allow3) Mode3Sell();
   if (TradingStatus == mode4buy  && Allow4) Mode4Buy();
   if (TradingStatus == mode4sell && Allow4) Mode4Sell();
   if (TradingStatus == mode7buy  && Allow7) Mode7Buy();
   if (TradingStatus == mode7sell && Allow7) Mode7Sell();
   ///////////////////////////////////////////////////////////////////////////////////////////////      
   DisplayUserFeedback();
//----
   return(0);
}
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|     calcMACD_BB                                                  |  
//+------------------------------------------------------------------+
void calcMACD_BB( string strPair, int intTF, int intFastMA, int intSlowMA,
                  int intSigMA, int intSigMAMode, int intBBPeriod,
                  int intBBDev, double& adblData[], int intShift )
{
   double adblMACD[];
   int intSize = MathMax( intBBPeriod, intSigMA ) + 1;
   
   ArrayResize( adblMACD, intSize );
   ArraySetAsSeries( adblMACD, true );
   
   for ( int inx = 0; inx < intSize; inx++ )
   {
      adblMACD[inx] = iMACD( strPair, intTF, intFastMA, intSlowMA, 1, PRICE_CLOSE, MODE_MAIN, intShift+inx );
   }
   
   adblData[0] = adblMACD[0];
   adblData[1] = iBandsOnArray( adblMACD, 0, intBBPeriod, intBBDev, 0, MODE_MAIN, 0 );
   adblData[2] = iBandsOnArray( adblMACD, 0, intBBPeriod, intBBDev, 0, MODE_UPPER, 0 );     
   adblData[3] = iBandsOnArray( adblMACD, 0, intBBPeriod, intBBDev, 0, MODE_LOWER, 0 );
   adblData[4] = iMAOnArray( adblMACD, 0, intSigMA, 0, intSigMAMode, 0 ); 
}
//+------------------------------------------------------------------+
//| TotalCurrLOT                                                     |
//+------------------------------------------------------------------+
double TotalCurrLOT(string cur)
{  int i=0; double TotalLots=0;
   while(i<OrdersTotal())
   { OrderSelect(i,SELECT_BY_POS,MODE_TRADES);i++;
     if(StringSubstr(OrderSymbol(), 0, 3)==cur || StringSubstr(OrderSymbol(), 3, 3)==cur )
     TotalLots=TotalLots+OrderLots();
   }
   return(TotalLots);
}

