//+------------------------------------------------------------------+
//|            Steve Hopwood's Trend_Range detecting auto-trader.mq4 |
//|                                  Copyright © 2010, Steve Hopwood |
//|                              http://www.hopwood3.freeserve.co.uk |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2010, Steve Hopwood"
#property link      "http://www.hopwood3.freeserve.co.uk"
#property show_inputs
#include <WinUser32.mqh>
#include <stdlib.mqh>
#define  NL    "\n"
//Direction definitions for trend break trading
#define  up "Up"
#define  down "Down"
#define  ranging "Ranging"
#define  confused "Confused, and so cannot trade"
#define  trending "Trending"
/*

Modules:
TREND DETECTION MODULE
TREND TRADING MODULE
RANGE TRADING MODULE
COMMON FUNCTIONS MODULE
TRADE MANAGEMENT MODULE

int start()
void DisplayUserFeedback()



----Trend direction----
void GetTheTrend()
void GetRsiTrend()
void GetAtrTrend()
void GetAdxTrend()

----Trend trading----
void TrendTrading()
void TradeMovingAverageCross()
void TradeOctoSRC()

----Range trading----
void RangeTrading()
void TradeBollingerBands{}


----Common functions----
bool DoesTradeExist(int magic)
bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take, int magic)
double double GetMovingAverage(int tf, int period, int method, int AppliedPrice, int shift)
double GetTakeProfit(int type, double price, int shift)
double GetStopLoss(int type, double price, int shift)

----Trade Management----
void ManageOpenTrades()
bool CloseTrade()
void CheckForRsiExit()
CheckForAdxExit()
void UpdateChandelierTrailingStop()
void CheckTrendToRangeViceVersa(string type)

*/


extern string  gi="____General inputs----";
extern double  Lot=0.01;
extern bool    CriminalIsECN=false;
extern bool    StopTrading=false;
extern string  bl1="-------------------------------------------------------------";
extern string  tm="----Trend detection module----";
extern string  rsin="----Rsi----";
extern bool    UseRsi=false;
extern int     RsiTf=0;
extern int     RsiPeriod=21;
extern string  atri="----Atr----";
extern bool    UseAtr=true;
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  exi="----Trade Exit Strategies----";
extern string  es1="    --------------";
extern string  sltp="Set sl & tp in pips";
extern bool    UseSetTakeProfit=false;
extern int     TakeProfit=50;
extern bool    UseSetStopLoss=false;
extern int     StopLoss=0;
extern string  es2="    --------------";
extern string  satr="Atr sl and tp";
extern int     AtrTpSlTf=0;
extern int     AtrTpSlPeriod=21;
extern bool    UseAtrTakeProfit=true;
extern double  AtrTpMultiplier=2;
extern bool    UseAtrStopLoss=true;
extern double  AtrSlMultiplier=1;
extern string  es3="    --------------";
extern string  rsisl="Rsi exit";
extern bool    UseRsiExit=false;
extern int     RsiExitOverBought=70;
extern int     RsiExitOverSold=30;
extern int     RsiExitTf=0;
extern int     RsiExitPeriod=21;
extern string  es5="    --------------";
extern string  adex="Adx exit";
extern bool    UseAdxExit=false;
extern double  AdxExitValue=35;
extern int     AdxExitTf=0;
extern int     AdxExitPeriod=21;
extern string  es7="    --------------";
extern string  etrc="Exit on change of trend to range or vice versa";
extern bool    UseTrendToRangeViceVersaExit=true;
extern string  es6="    --------------";
extern string  cha="Chandelier trailing stop";
extern bool    UseChandelier=true;
extern int     ChandelierAtrMultiplier=3;
extern string  bl2a="-------------------------------------------------------------";
/////////////////////////////////////////////////////////////////////////////////////////////////
//With the addition of each new strategy,remember to make the appropriate changes to void ManageOpenTrades()
/////////////////////////////////////////////////////////////////////////////////////////////////
extern string  str="----Trend Trading Strategies----";
extern string  mac="Moving Average Cross";
extern bool    TradeMovingAverageCross=true;
extern int     MacMagicNumber=284650;
extern string  MacTradeComment="Mac";
extern int     MacFastMaPeriod=10;
extern int     MacFastMethod=0;//simple. 1=exponential: 2=smoothed; 3 = linear weighted
extern int     MacFastAppliedPrice=0;//close: 1=open; 2=high; 3=low; 4=median; 5=typical; 6=weighted
extern int     MacSlowMaPeriod=20;
extern int     MacSlowMethod=0;
extern int     MacSlowAppliedPrice=0;
extern int     MacTf=0;
extern string  es8="    --------------";
extern string  oct="Octomanoak Simple Reversal Candle Strategy";
extern bool    TradeOctoSRC=true;
extern int     OctoMagicNumber=284652;
extern string  OctoTradeComment="Oct";
extern int     OctoRsiPeriod=21;
extern int     OctoRsiAppliedPrice=0;
extern int     OctoMinRsiMovement=8;
extern int     OctoTakeProfitPips=20;
extern string  bl3="-------------------------------------------------------------";
extern string  rts="----Range Trading Strategies----";
extern string  bbrt="Bollinger Bands";
extern bool    TradeBollingerBands=true;
extern int     BbMagicNumber=284651;
extern string  BbTradeComment="BB";
extern int     BbPeriod=25;
extern int     BbDeviations=2;
extern int     BbAppliedPrice=0;
extern int     BbTf=0;
extern string  bl4="-------------------------------------------------------------";
extern string  tt="----Trading hours----";
extern string  Trade_Hours= "Set Morning & Evening Hours";
extern string  Trade_Hoursi= "Use 24 hour, local time clock";
extern string  Trade_Hours_M= "Morning Hours 0-12";
extern  int    start_hourm = 0;
extern  int    end_hourm = 12;
extern string  Trade_Hours_E= "Evening Hours 12-24";
extern  int    start_houre = 12;
extern  int    end_houre = 24;
extern string  mis="----Odds and ends----";
extern int     DisplayGapSize=30;
extern bool    ShowUserFeedback=true;


//Trend
double         TrendRsiVal, TrendAtrVal;
double         AdxVal, AdxPlusDI, AdxMinusDI;
string         RsiTrend, AtrTrend, AdxTrend, LsmaTrend, trend;

//OCTOMANOAK SIMPLE REVERSAL CANDLE STRATEGY
int            OctoMinPibsBreak=2;

//Small digit fix, for things liks x pips above the previous high
int            NoIs2=2;

//Candle size Stop Loss & Take Profit
bool           UseCsStopLoss=false;
bool           UseCsTakeProfit=false;


//Misc
string         Gap, DisabledMessage, ScreenMessage;
int            TicketNo;


//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+


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);
   if (!StopTrading) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Looking for trading opportunities", NL);
   if (StopTrading) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Not trading", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Lot size: ", Lot, NL);
//   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Take Profit: ", TakeProfit, NL);
//   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Stop Loss: ", StopLoss, NL);
//   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Magic number: ", MagicNumber, NL);
//   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trade comment: ", TradeComment, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Criminal's minimum lot size: ", MarketInfo(Symbol(), MODE_MINLOT), NL);
   if (CriminalIsECN) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "CriminalIsECN = true", NL);
   else ScreenMessage = StringConcatenate(ScreenMessage,Gap, "CriminalIsECN = false", NL);
   
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);
   if (UseRsi) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Rsi trend is ", RsiTrend, NL);
   if (UseAtr) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Atr trend is ", AtrTrend, NL);
   if (UseAdx) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Adx trend is ", AdxTrend, NL);
   if (UseLSMA) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "LSMA trend is ", LsmaTrend, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "This robot is working with trend = ", trend, NL);
   Comment(ScreenMessage);
   
}//End void DisplayUserFeedback()


int init()
{

   //Accommodate different quote sizes
   double multiplier;
   if(Digits == 2 || Digits == 4) multiplier = 1;
   if(Digits == 3 || Digits == 5) multiplier = 10;
   if(Digits == 6) multiplier = 100;   
   TakeProfit*= multiplier;
   StopLoss*= multiplier;
   OctoMinPibsBreak*= multiplier;
   OctoTakeProfitPips*= multiplier;
   NoIs2*= multiplier;
   
   
//----
   Gap="";
   if (DisplayGapSize >0)
   {
      for (int cc=0; cc< DisplayGapSize; cc++)
      {
         Gap = StringConcatenate(Gap, " ");
      }   
   }//if (DisplayGapSize >0)
   
   Comment(".....................Waiting for the next tick....................");

   //start();
   
   
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
//----
   Comment("");
//----
   return(0);
}//End int deinit()




///////////////////////////////////////////////////////////////////////////////////////////
//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 GetTradeDirectionFromTrend(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 GetTradeDirectionFromTrend()


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 = GetTradeDirectionFromTrend(LSMATf, 1);
      LsmaTrend = GetTradeDirectionFromTrend(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
///////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////
//COMMON FUNCTIONS MODULE
bool DoesTradeExist(int magic)
{
   
   //TicketNo = 0;
   
   if (OrdersTotal() == 0) return(false);
   
   for (int cc = OrdersTotal() - 1; cc >= 0 ; cc--)
   {
      if (!OrderSelect(cc,SELECT_BY_POS)) continue;
      
      if (OrderMagicNumber()== magic && OrderSymbol() == Symbol() )      
      {
         //TicketNo = OrderTicket();
         return(true);         
      }//if (OrderMagicNumber()==MagicNumber && OrderSymbol() == Symbol() )      
   }//for (int cc = OrdersTotal() - 1; cc >= 0 ; cc--)

   return(false);

}//End bool DoesTradeExist(int magic)

bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take, int magic)
{
   //Alert(price, "  ", stop);
   //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 = 10000;
   //if (Digits == 3 || Digits == 5) slippage = 100;
   
   color col = Red;
   if (type == OP_BUY || type == OP_BUYSTOP) col = Green;
   
   int expiry = 0;
   
   //Cater for a blank comment
   if (comment == "") comment = " ";
   
   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);
	   //TP && SL both > 0
      if (stop >0 && take > 0) bool result = OrderModify(OrderTicket(), OrderOpenPrice(), stop, take, OrderExpiration(), CLR_NONE);
      //Stop loss but no take profit
      if (stop >0 && take == 0) result = OrderModify(OrderTicket(), OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);
      //Take profit but no stop loss
      if (stop ==0 && take > 0) result = OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), take, OrderExpiration(), CLR_NONE);
      if (!result)
      {
          int err=GetLastError();
          Print(Symbol(), " SL/tprder modify failed with error(",err,"): ",ErrorDescription(err));               
      }//if (!result)			  
      
   }//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," Tiger order send failed with error(",err,"): ",ErrorDescription(err));
      Print(Symbol(), " ", stype," Tiger order send failed with error(",err,"): ",ErrorDescription(err),
            ": Price ", price, ": Sl ", stop, ": Tp ", take);
      return(false);
   }//if (ticket < 0)  
   
   //Got this far, so trade send succeeded
   return(true);
   
}//End bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take, int magic)

double GetMovingAverage(int tf, int period, int method, int AppliedPrice, int shift)
{

   double v = iMA(NULL, tf, period, 0, method, AppliedPrice, shift);
   
   return(v);

}//End double GetMovingAverage(int tf, int period, int method, int AppliedPrice, int shift)

double GetTakeProfit(int type, double price, int shift)
{

   double take;
   int tf, period;
   
   
   //Long tp
   if (type == OP_BUY || type == OP_BUYSTOP)
   {
      
      //Hard pips
      if (UseSetTakeProfit) take = NormalizeDouble(price + (TakeProfit * Point), Digits);
      
      //Atr
      if (UseAtrTakeProfit) 
      {
         tf = AtrTpSlTf;
         period = AtrTpSlPeriod;
         if (period == 0) period = Period();
         
         if (tf == 0) tf = Period();
         
         double v = iATR(NULL, tf, period, 0);
         take = NormalizeDouble(price + (v * AtrTpMultiplier), Digits);
      }//if (UseAtrTakeProfit)
   
      //Candle size
      if (UseCsTakeProfit)
      {
         take = NormalizeDouble(High[shift], Digits);
      }//if (UseCsTakeProfit)
   
   
   }//if (type == OP_BUY || type == OP_BUYSTOP)
      
   //Short tp
   if (type == OP_SELL || type == OP_SELLSTOP)
   {
      //Hard pips
      if (UseSetTakeProfit) take = NormalizeDouble(price - (TakeProfit * Point), Digits);
      
      //Atr
      if (UseAtrTakeProfit) 
      {
         tf = AtrTpSlTf;
         period = AtrTpSlPeriod;
         if (period == 0) period = Period();         
         if (tf == 0) tf = Period();         
         v = iATR(NULL, tf, period, 0);
         take = NormalizeDouble(price - (v * AtrTpMultiplier), Digits);
      }//if (UseAtrTakeProfit)
   
      //Candle size
      if (UseCsTakeProfit)
      {
         take = NormalizeDouble(Low[shift], Digits);
      }//if (UseCsTakeProfit)
   
   }//if (type == OP_SELL || type == OP_SELLSTOP)
      
   return(take);
   
}//End double GetTakeProfit(int type, double price, int shift)

double GetStopLoss(int type, double price, int shift)
{

   double stop;
   int tf, period;
   
   
   //Long sl
   if (type == OP_BUY || type == OP_BUYSTOP)
   {
      //Hard pips stop
      if (UseSetStopLoss) stop = NormalizeDouble(price - (StopLoss * Point), Digits);
      
      //Atr stop
      if (UseAtrStopLoss) 
      {
         tf = AtrTpSlTf;
         if (tf == 0) tf = Period();
         
         
         double v = iATR(NULL, tf, AtrTpSlPeriod, 0);
         stop = NormalizeDouble(price - (v * AtrSlMultiplier), Digits);               
      }//if (UseAtrStopLoss)
      
      //Candle size stop loss
      if (UseCsStopLoss)
      {
         double spread = MarketInfo(Symbol(), MODE_SPREAD);
         stop = NormalizeDouble(Low[shift] - (spread * Point), Digits);
      }//if (UseCsStopLoss)
      
   
   }//if (type == OP_BUY || type == OP_BUYSTOP)
      
   //Short sl
   if (type == OP_SELL || type == OP_SELLSTOP)
   {
      //Hard pips stop
      if (UseSetStopLoss) stop = NormalizeDouble(price + (StopLoss * Point), Digits);
      
      //Atr stop
      if (UseAtrStopLoss) 
      {
         tf = AtrTpSlTf;
         if (tf == 0) tf = Period();
         v = iATR(NULL, tf, AtrTpSlPeriod, 0);
         stop = NormalizeDouble(price + (v * AtrSlMultiplier), Digits);
      }//if (UseAtrStopLoss)
   
      //Candle size stop loss
      if (UseCsStopLoss)
      {
         spread = MarketInfo(Symbol(), MODE_SPREAD);
         stop = NormalizeDouble(High[shift] + (spread * Point), Digits);
      }//if (UseCsStopLoss)
   
   
   }//if (type == OP_SELL || type == OP_SELLSTOP, int shift)
      
   return(stop);
   
}//End double GetStopLoss(int type, double price)


//END COMMON FUNCTIONS MODULE
///////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////
//TREND TRADING MODULE

void TradeMovingAverageCross()
{
   if (DoesTradeExist(MacMagicNumber)) return;
   
   double tf = MacTf;
   if (tf == 0) tf = Period();
   
   double FastMa = GetMovingAverage(tf, MacFastMaPeriod, MacFastMethod, MacFastAppliedPrice, 0);
   double SlowMa = GetMovingAverage(tf, MacSlowMaPeriod, MacSlowMethod, MacSlowAppliedPrice, 0);
   
   //Look for long cross
   if (trend == up)
   {
      if (Ask > SlowMa && Open[0] < SlowMa)
      {
         RefreshRates();
         double take = GetTakeProfit(OP_BUY, Ask, 0);
         double stop = GetStopLoss(OP_BUY, Ask, 0);
         bool result = SendSingleTrade(OP_BUY, MacTradeComment, Lot, Ask, stop, take, MacMagicNumber);
      }//if (Ask > SlowMa && Open[0] < SlowMa)
      
   }//if (trend == up)
   
   //Look for short cross
   if (trend == down)
   {
      if (Bid < SlowMa && Open[0] > SlowMa)
      {
         RefreshRates();
         take = GetTakeProfit(OP_SELL, Bid, 0);
         stop = GetStopLoss(OP_SELL, Bid, 0);
         result = SendSingleTrade(OP_SELL, MacTradeComment, Lot, Bid, stop, take, MacMagicNumber);
      }//if (Bid < SlowMa && Open[0] > SlowMa)
      
   }//if (trend == down)
   

}//End void TradeMovingAverageCross()

void TradeOctoSRC()
{
/*
extern int     OctoMagicNumber=284652;
extern string  OctoTradeComment="Oct";
extern int     OctoRsiPeriod=21;
extern int     OctoRsiAppliedPrice=0;
OctoMinRsiMovement
*/

   if (DoesTradeExist(OctoMagicNumber)) return;
   
   //Rsi must be OctoMinRsiMovement points higher than 2 candles ago
   double RsiNow, RsiThen;
   RsiNow = iRSI(NULL, 0, OctoRsiPeriod, OctoRsiAppliedPrice, 0);
   RsiThen = iRSI(NULL, 0, OctoRsiPeriod, OctoRsiAppliedPrice, 2);
   if (MathAbs(RsiNow - RsiThen) < OctoMinRsiMovement) return;
   
   //Looking for a buy
   if (trend == up)
   {
      //2 candles ago must be a down
      if (Close[2] > Open[2]) return;
      //1 candle ago must be an up
      if (Close[1] < Open[1]) return;
      //Rsi must be rising
      if (RsiNow < RsiThen) return;
      //Current candle must be >= OctoMinPibsBreak above the previous candle's high
      if (Ask < High[1] + (OctoMinPibsBreak * Point) ) return;
      //Got this far, so send the trade
      RefreshRates();
      UseCsStopLoss = true;
      double stop = GetStopLoss(OP_BUY, Ask, 0);
      UseCsStopLoss = false;
      double take = GetTakeProfit(OP_BUY, Ask, 0);         
      if (take == 0) take = NormalizeDouble(Ask + (OctoTakeProfitPips * Point), Digits);
      take = NormalizeDouble(Ask + (200 * Point), Digits);
      
      bool result = SendSingleTrade(OP_BUY, OctoTradeComment, Lot, Ask, stop, take, OctoMagicNumber);
   }//if (trend == up)
   

   //Looking for a sell
   if (trend == down)
   {
      //2 candles ago must be an up
      if (Close[2] < Open[2]) return;
      //1 candle ago must be a down
      if (Close[1] > Open[1]) return;
      //Rsi must be rising
      if (RsiNow > RsiThen) return;
      //Current candle must be >= OctoMinPibsBreak above the previous candle's high
      if (Bid > Low[1] - (OctoMinPibsBreak * Point) ) return;
      //Got this far, so send the trade
      UseCsStopLoss = true;
      stop = NormalizeDouble(GetStopLoss(OP_SELL, Bid, 2) - (NoIs2 * Point), Digits);
      UseCsStopLoss = false;
      take = GetTakeProfit(OP_SELL, Bid, 0);
      if (take == 0) take = NormalizeDouble(Bid - (OctoTakeProfitPips * Point), Digits);
      
      result = SendSingleTrade(OP_SELL, OctoTradeComment, Lot, Bid, stop, take, OctoMagicNumber);
   }//if (trend == down)
   

}//End void TradeOctoSRC()


void TrendTrading()
{

   //Moving average cross
   if (TradeMovingAverageCross) TradeMovingAverageCross();
   if (TradeOctoSRC) TradeOctoSRC();
   
}//End void TrendTrading()

//END TREND TRADING MODULE
///////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////
//RANGE TRADING MODULE

void TradeBollingerBands()
{
   //Trades the bounce off the upper and lower lines

   if (DoesTradeExist(BbMagicNumber)) return;
   
   double BbUpper = iBands(NULL, BbTf, BbPeriod, BbDeviations, 0, BbAppliedPrice, MODE_UPPER, 0);
   double BbLower = iBands(NULL, BbTf, BbPeriod, BbDeviations, 0, BbAppliedPrice, MODE_LOWER, 0);
   double stop, take;
   
   //Look for a short off the upper band
   if (Ask >= BbUpper)
   {
      RefreshRates();
      take = GetTakeProfit(OP_SELL, Bid, 0);
      stop = GetStopLoss(OP_SELL, Bid, 0);
      bool result = SendSingleTrade(OP_SELL, BbTradeComment, Lot, Bid, stop, take, BbMagicNumber);
   }//if (Ask >= BbUpper)
   
   //Look for a long off the lower band
   if (Bid <= BbLower)
   {
      RefreshRates();
      take = GetTakeProfit(OP_BUY, Ask, 0);
      stop = GetStopLoss(OP_BUY, Ask, 0);
      result = SendSingleTrade(OP_BUY, BbTradeComment, Lot, Ask, stop, take, BbMagicNumber);
   }//if (bid <= BbLower)
   

}//void TradeBollingerBands{}


void RangeTrading()
{
   if (TradeBollingerBands) TradeBollingerBands();
   

}//void RangeTrading()


//END RANGE TRADING MODULE
///////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////
//TRADE MANAGEMENT MODULE

bool CloseTrade()
{

   bool result = OrderClose(TicketNo, OrderLots(), OrderClosePrice(), 1000, Blue);
   if (!result)
   {
       int err=GetLastError();
       Print(Symbol(), " ", TicketNo, " order failed to close with error(",err,"): ",ErrorDescription(err));               
   }//if (!result)      
   if (result) return(true);
   else return(false);
   
}//bool CloseTrade()


void CheckForRsiExit()
{

   int tf = RsiExitTf;
   if (tf == 0) tf = Period();
   double v = iRSI(NULL, tf, RsiExitPeriod, PRICE_CLOSE, 0);

   //Long trade
   if (OrderType() == OP_BUY)
   {
      if (v >= RsiExitOverBought) CloseTrade();   
   }//if (OrderType() == OP_BUY)
   
   //Short trade
   if (OrderType() == OP_BUY)
   {
      if (v <= RsiExitOverSold) CloseTrade();   
   }//if (OrderType() == OP_BUY)
   

}//void CheckForRsiExit()

void CheckForAdxExit()
{

   int tf = AdxExitTf;
   if (tf == 0) tf = Period();
   double v = iADX(NULL, tf, AdxExitPeriod, PRICE_CLOSE, MODE_MAIN, 0);

   //Long trade
   if (OrderType() == OP_BUY)
   {
      if (v >= AdxExitValue) CloseTrade();   
   }//if (OrderType() == OP_BUY)
   
   //Short trade
   if (OrderType() == OP_BUY)
   {
      if (v <= AdxExitValue) CloseTrade();   
   }//if (OrderType() == OP_BUY)


}//CheckForAdxExit()

void UpdateChandelierTrailingStop()
{
/*
- this is an interesting one invented by Chuck LeBeau, one of the best traders in the business. 
- He calls it the chandelier because the stop loss hangs off the most recent high in an uptrend. 
- Not sure what he calls in during a down trend – 'bar stool' perhaps? For a buy trade (reverse everything for a 
  sell trade):
- Each time the market makes a new high, the stop loss is moved by this price minus Atr * ChandelierAtrMultiplier. 
- Because Atr can change quickly with increasing/decreasing market volatility, this becomes a highly adaptable 
  stop that moves lower during volatile periods and higher during stable ones.
- This is a trend-trading stop loss, so  the ChandelierAtrMultiplier will decrease as the trade becomes more profitable, 
  initially reducing risk and eventually locking in more of the profits:
- when the profit reaches a multiple of 4 Atr's,  ChandelierAtrMultiplier will reduce to 2.
- when the profit reaches a multiple of 6 Atr's,  ChandelierAtrMultiplier will reduce to 1.

extern string  es6="    --------------";
extern string  cha="Chandelier trailing stop";
extern bool    UseChandelier=true;
extern int     ChandelierAtrMultiplier=3;
*/

   //Does ChandelierAtrMultiplier need reducing?
   if (OrderProfit() > 0)
   {
      if (MathAbs(OrderOpenPrice() - OrderClosePrice() ) > TrendAtrVal * 4 && ChandelierAtrMultiplier > 2) ChandelierAtrMultiplier = 2;
      if (MathAbs(OrderOpenPrice() - OrderClosePrice() ) > TrendAtrVal * 6 && ChandelierAtrMultiplier > 1) ChandelierAtrMultiplier = 1;
   }//if (OrderPrint() > 0)
   
   double stop;
   double target = TrendAtrVal * ChandelierAtrMultiplier;
   
   //Check long trades
   if (OrderType() == OP_BUY)
   {
      if (OrderClosePrice() - OrderStopLoss() > target)
      {
         stop = NormalizeDouble(OrderClosePrice() - target, Digits);
         bool result = OrderModify(OrderTicket(), OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);
         if (!result)
         {
             int err=GetLastError();
             Print(Symbol(), " SL/tprder modify failed with error(",err,"): ",ErrorDescription(err));               
         }//if (!result)      
      }//if (OrderClosePrice() - OrderStopLoss() > TrendAtrVal * ChandelierAtrMultiplier)
   }//if (OrderType() == OP_BUY)
   
   //Check short trades
   if (OrderType() == OP_SELL)
   {
      if (OrderStopLoss() - OrderClosePrice() > target)
      {
         stop = NormalizeDouble(OrderClosePrice() + target, Digits);
         result = OrderModify(OrderTicket(), OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);
         if (!result)
         {
             err=GetLastError();
             Print(Symbol(), " SL/tprder modify failed with error(",err,"): ",ErrorDescription(err));               
         }//if (!result)      
      }//if (OrderClosePrice() - OrderStopLoss() > TrendAtrVal * ChandelierAtrMultiplier)
   }//if (OrderType() == OP_SELL)
   

}//End void UpdateChandelierTrailingStop()

void CheckTrendToRangeViceVersa(string type)
{

   //Close trend trades on a return to tanging
   if (type == trending && trend == ranging) CloseTrade();
   if (type == ranging && trend == trending) CloseTrade();
   

}//End void CheckForTrendChangeToRangeViceVersa(string type)



void ManageOpenTrades()
{

   /*
   Working out which trades belong to this robot is complicated because each system has its own
   magic number. The if(OrderMagicNumber() == xxxMagicNumber) is going to become rather long as
   I add new trading systems.
   */
   for (int cc = OrdersTotal() - 1; cc >=0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if(OrderMagicNumber() == MacMagicNumber || OrderMagicNumber() == BbMagicNumber
         || OrderMagicNumber() == OctoMagicNumber )
      {
         TicketNo = OrderTicket();//In case the order ever needs re-selecting, or for a check that it is still open
         if (UseRsiExit) CheckForRsiExit();
         if (UseAdxExit) CheckForAdxExit();
         if (UseChandelier) UpdateChandelierTrailingStop();
         if (UseTrendToRangeViceVersaExit) 
         {   
            string type;
            if (OrderMagicNumber() == MacMagicNumber) type = trending;
            if (OrderMagicNumber() == OctoMagicNumber) type = trending;
            if (OrderMagicNumber() == BbMagicNumber) type = ranging;
            CheckTrendToRangeViceVersa(type);
         }//if (UseTrendToRangeViceVersa) 
            
      }//if(OrderMagicNumber() == MacMagicNumber)
      
   
   }//for (int cc = OrdersTotal() - 1; cc >=0; cc--)
   

}//void ManageOpenTrades()


//END TRADE MANAGEMENT MODULE
///////////////////////////////////////////////////////////////////////////////////////////
bool TradingTimesCheck()
{

      //Trading times
   int hour = TimeHour(TimeLocal() );
   
   if (end_hourm < start_hourm)
	{
		end_hourm += 24;
	}
	

	if (end_houre < start_houre)
	{
		end_houre += 24;
	}
	
	bool ok2Trade = (hour >= start_hourm && hour <= end_hourm) || (hour >= start_houre && hour <= end_houre);

	// adjust for past-end-of-day cases
	// eg in AUS, USDJPY trades 09-17 and 22-06
	// so, the above check failed, check if it is because of this condition
	if (!ok2Trade && hour < 12)
	{
 		hour += 24;
		ok2Trade = (hour >= start_hourm && hour <= end_hourm) || (hour >= start_houre && hour <= end_houre);
		
		// so, if the trading hours are 11pm - 6am and the time is between  midnight to 11am, (say, 5am)
		// the above code will result in comparing 5+24 to see if it is between 23 (11pm) and 30(6+24), which it is...
	}


   // check for end of day by looking at *both* end-hours

   if (hour >= MathMax(end_hourm, end_houre))
   {      
      return(false);
   }//if (hour >= MathMax(end_hourm, end_houre))

   return(true);

}//End bool TradingTimesCheck()

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{


   if (OrdersTotal() > 0) ManageOpenTrades();

   /*if(DayOfWeek()== 1) StopTrading = True;
   if(DayOfWeek()== 2) {
      StopTrading = False;
      AtrTpMultiplier = 2.2;
      AtrSlMultiplier = 1.2;
   }
   if(DayOfWeek()== 3) StopTrading = True;
   if(DayOfWeek()== 4) {
      StopTrading = False;
      AtrTpMultiplier = 2.0;
      AtrSlMultiplier = 2.0;
   }
   if(DayOfWeek()== 5) StopTrading = True;
   */
   if (StopTrading) return;
   
   
   
   bool TradeHours = TradingTimesCheck();
   if (!TradeHours)
   {
      return;
   }

   ///////////////////////////////////////////////////////////////////
   //Trend direction
   GetTheTrend();   
   ///////////////////////////////////////////////////////////////////

   if (ShowUserFeedback) DisplayUserFeedback();
   
   if (trend == confused) return;//Cannot trade
   
   ///////////////////////////////////////////////////////////////////
   //Trend trading
   if (trend == up || trend == down)
   {
      TrendTrading();      
   }//if (trend == up || trend == down)
     
   ///////////////////////////////////////////////////////////////////
   
   ///////////////////////////////////////////////////////////////////
   //Range trading
   if (trend == ranging)
   {
      RangeTrading();
   }//if (trend == ranging)
     
   ///////////////////////////////////////////////////////////////////
   
   
      
}//End int start()

//+------------------------------------------------------------------+5