//+------------------------------------------------------------------+
//|           Steve Hopwood's BS 2 Moving Average and MACD combo.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"
//MACD direction
#define long "Long"
#define short "Short"
#define none "None"


/*

/*

void DisplayUserFeedback()
void AdjustFor4digitCriminal()
start()

----Trading functions----
void LookForOpenTrades()
bool SendSingleTrade(int type)
double SetAggressiveStopLoss(int type)
double SetConservativeStopLoss(int type)
bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop )
void GetSpread()
void ShouldHalfTradeClose()
bool ShouldRobotSleep()

----TP and SL
void TrailingStopLoss()
void JumpingStopLoss(int ticket) ---- not used in this robot but left in place and commented out in case it is required

----SMA & MACD----
GetSmaTradeDirection()
void GetMacdDirection()

********News filter functions***********
Thanks to Tim at FXAW for all this
bool NewsFilterCheck()
      Use construct bool TradeAllowed = NewsFilterCheck()
string Num2Impact(int impact)

----Misc----
void WaitForConnection()

*/
extern string     bs="----Basic stuff----";
extern bool       LongTradeAllowed=true;//Allows user to disable trading
extern bool       ShortTradeAllowed=true;//Allows user to disable trading
extern double     Lot=0.02;
extern int        MagicNumber=6381345;
extern string     TradeComment="5MM";
extern int        MaxSpread=120;
extern int        SleepAfterTradeClosesMins=0;
extern string     slc="Stop Loss: Choose 1 setting";
extern bool       Aggressive=false;
extern bool       Conservative=true;
extern string     sls="----Trade management----";
//extern string     JSL="Jumping stop loss";
//extern bool       JumpingStop=false;
//extern int        JumpingStopPips=1000;
//extern bool       AddBEP=true;
//extern int        BreakEvenProfit=100;
//extern bool       HideJumpingStop=false;
//extern int        PipsAwayFromVisualJS=100;
extern string     TSL="Trailing stop loss";
extern bool       HideTrailingStop=false;
extern int        PipsAwayFromVisualTS=50;
extern string     news="-----News filter-----";
extern bool       UseNewsFilter=true;
extern int        MinsUntilNews=60;
extern string     news1="3=High; 2=Medium; 1=Low";
extern int        NewsImpact=3;
extern string     oae="----Odds and ends----";
extern int        DisplayGapSize=30;



//Open trades\trade direction.
bool              TradeOpen;
int               TicketNo;
string            TradeDirection;
int               ConservativeSlPips=200;
   
//Sma and MACD
string            MacdDirection;
double            MacdVal;
double            Ema;
double            MinBreakPips=100;

//Misc stuff
string            ScreenMessage, Gap;
int               NewsBars;
bool              RobotDisabled;
string            DisabledMessage;
int               Spread;

void DisplayUserFeedback()
{
   ScreenMessage = "";
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, "20 ESMA = ", DoubleToStr(Ema, Digits), NL);
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Trade direction = ", TradeDirection, NL);
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, "MACD = ", MacdVal, NL);
   //if (!TradeDirection == none) ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Usable Macd direction = ", MacdDirection, NL);
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Macd direction = ", MacdDirection, NL);
   
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, NL);
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Lot size = ", Lot, NL);
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Stop loss selection = ");
   if (Aggressive) ScreenMessage = StringConcatenate(ScreenMessage, "Aggressive", NL);
   if (Conservative) ScreenMessage = StringConcatenate(ScreenMessage, "Conservative", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Magic number = ", MagicNumber, NL);
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Trade comment = ", TradeComment, NL);
   if (LongTradeAllowed) ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Long trading is allowed", NL);
   else ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Long trading is disabled", NL);
   if (ShortTradeAllowed) ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Short trading is allowed", NL);
   else ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Short trading is disabled", NL);
   GetSpread();
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, "MaxSpread = ", MaxSpread, "  Spread = ", Spread, NL);
   ScreenMessage=StringConcatenate(ScreenMessage, Gap, "The robot will sleep for ", SleepAfterTradeClosesMins, " mins after a trade closure",NL);
   //News filter
   if (UseNewsFilter) 
   {
      NewsFilterCheck();
   }//if (UseNewsFilter)  
   
   /*  
   if(JumpingStop==true)
   {
      ScreenMessage = StringConcatenate(ScreenMessage,  NL, Gap, "Jumping stop set to ", JumpingStopPips);
      if (HideJumpingStop)  ScreenMessage = StringConcatenate(ScreenMessage, " (HideJumpingStop = true: PipsAwayFromVisualJS = ", PipsAwayFromVisualJS, ")");
      if(AddBEP==true)
      {
         ScreenMessage = StringConcatenate(ScreenMessage, ", also adding BreakEvenProfit (", BreakEvenProfit, " pips)");      
      }      
   }
   else
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, Gap, "Jumping stop disabled");
   }
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, NL);
   */
   if (TradeOpen) ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Trade open  ", TicketNo, NL);
   

   Comment(ScreenMessage);
}//void DisplayUserFeedback()


//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
//----
   
   if (!IsDemo() )
   {
      if (MagicNumber == 6381345)
      {
         MessageBox("You cannot run this robot until changed the MagicNumber input from the default of 6381345." + NL 
                    + "Please reload the robot with a new MagicNumber input.");
         Comment("                This robot can do nothing. Please reload it");
         DisabledMessage = "You need to change the MagicNumber input";
         RobotDisabled = true;
         return;
      }//if (MagicNumber == 4872635)
      
      //Insufficient length
      string mn = DoubleToStr(MagicNumber,0);
      if (StringLen(mn) < 5)
      {
         MessageBox("Your MagicNumber input needs to be at least 5 digits long, Your MagicNumber is " + mn + NL 
                    + "Please reload the robot with the MagicNumber input containing at least 5 digits - the more the better.");
         Comment("                This robot can do nothing. Please reload it");
         DisabledMessage = "You need to make the MagicNumber input at 5 digits long - more is better";
         RobotDisabled = true;
         return;
      }//if (StringLen(mn) < 5)
      
      //Default trade comment needs changing
      if (TradeComment == "5mm")
      {
         MessageBox("You cannot run this robot until changed the TradeComment input from the default of 5MM." + NL 
                    + "Please reload the robot with a new TradeComment input.");
         Comment("                This robot can do nothing. Please reload it");
         DisabledMessage = "You need to change the TradeComment input";
         RobotDisabled = true;
         return;
      }//if (MagicNumber == 876987)            
   }//if (!IsDemo)
   
   
   if (Period() != PERIOD_M5)
   {
      MessageBox("This is a M5 trading strategy. Consider changing the timr frame on your chart.");
   }//if (Period() != PERIOD_D1 && Period() != PERIOD_H1)
   
   
   Gap="";
   if (DisplayGapSize >0)
   {
      for (int cc=0; cc< DisplayGapSize; cc++)
      {
         Gap = StringConcatenate(Gap, " ");
      }   
   }

   
   
//----
   return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
//----
   Comment("");
//----
   return(0);
}

double SetAggressiveStopLoss(int type)
{
   //Returns a stop that is the highest\lowest of the previous 5 bars
   
   if (type == 0)
   {
      double stop = Low[0];
      for (int cc = 1; cc < 5; cc++)
      {
         if (Low[cc] < stop) stop = Low[cc];
      }//if (type = 0)   
   }//if (type == 0)

   if (type == 1)
   {
      stop = High[0];
      for (cc = 1; cc < 5; cc++)
      {
         if (High[cc] > stop) stop = High[cc];
      }//if (type = 0)   
   }//if (type == 0)

   return(stop);

}//End double SetAggressiveStopLoss(int type)

double SetConservativeStopLoss(int type)
{
   //Returns a stop that is 20 pips below 20-period EMA
   
   if (type == 0)
   {
      double stop = NormalizeDouble(Ema - (ConservativeSlPips * Point), Digits);
      
   }//if (type == 0)

   if (type == 1)
   {
      stop = NormalizeDouble(Ema + (ConservativeSlPips * Point), Digits);
      
   }//if (type == 0)

   return(stop);

}//End double SetConservativeStopLoss(int type)


bool SendSingleTrade(int type)
{
   // Attempts to place a trade according to type, i.e.
   // 0 = OP_BUY
   // 1 = OP_SELL
   
   // Check spread
   if (MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread)
   {
      return(false);// Spread too large, so abort send
   }//if (MarketInfo(NULL, MODE_SPREAD) > MaxSpreadAllowed)
   
   WaitForConnection();
   RefreshRates();
   
   double StopLoss;
      
   // Buy trade
   if (type == 0)
   {
      double TradePrice=Ask;
      int colour = 32768;//green
      if (Aggressive) StopLoss = SetAggressiveStopLoss(0);
      if (Conservative) StopLoss = SetConservativeStopLoss(0);
   }//if (type == 0)   
   
   
   // Sell trade
   if (type == 1)
   {
      TradePrice=Bid;      
      colour = 255;//red
      if (Aggressive) StopLoss = SetAggressiveStopLoss(1);
      if (Conservative) StopLoss = SetConservativeStopLoss(1);
   }//if (type == 1)
   
   
   int slippage = 10;
   if (Digits == 3 || Digits == 5) slippage = 100;
   
   int ticket = OrderSend(Symbol(),type, Lot, TradePrice, slippage, StopLoss, 0, TradeComment, MagicNumber,0, colour);
   if (ticket < 0)
   {
      int err=GetLastError();
      Alert(Symbol(), " ", type," order send failed with error(",err,"): ",ErrorDescription(err));
      Print("Order send failed with error(",err,"): ",ErrorDescription(err));
      return(false);
   }//if (ticket < 0)
   else Sleep(1000);//1 second   
   
   return(true);
   
}//End bool SendSingleTrade(int type)

bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop )
{
   //Reusable code that can be called by any of the stop loss manipulation routines except HiddenStopLoss().
   //Checks to see if the market has hit the hidden sl and attempts to close the trade if so. 
   //Returns true if trade closure is successful, else returns false
   
   //Check buy trade
   if (type == OP_BUY)
   {
      double sl = NormalizeDouble(stop + (iPipsAboveVisual * Point), Digits);
      if (Bid <= sl)
      {
         bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {
            Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            int err=GetLastError();
            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)
         {
            Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            err=GetLastError();
            Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (Ask >= sl)  
   }//if (type = OP_SELL)
   

}//End bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop )

/*
void JumpingStopLoss(int ticket) 
{
   if (!OrderSelect(ticket, SELECT_BY_TICKET) ) return;//Order has closed, so nothing to do
   
   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)
            {
               Print("Jumping stop set at breakeven: ", OrderSymbol(), ": SL ", sl, ": Ask ", Ask);
               //Delete the associated hedge trade
               return(0);
            }//if (result)
            if (!result)
            {
               int err=GetLastError();
               Alert(Symbol(), " buy trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err));
               Print(Symbol(), " buy trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err));
            }//if (!result)
             
            
         }//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)
         {
            Print("Jumping stop set: ", OrderSymbol(), ": SL ", sl, ": Ask ", Ask);
            //Delete the associated hedge trade
            return(0);
         }//if (result)
         if (!result)
         {
            err=GetLastError();
            Print(Symbol(), " 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();
               Alert(Symbol(), " sell trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err));
               Print(Symbol(), " 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)
         {
            Print("Jumping stop set: ", OrderSymbol(), ": SL ", sl, ": Ask ", Ask);
            
         }//if (result)          
         if (!result)
         {
            err=GetLastError();
            Print(Symbol(), " sell trade. Jumping stop function failed with error(",err,"): ",ErrorDescription(err));
         }//if (!result)

      }// close if (Bid>= sl + (JumpingStopPips*Point) && sl>= OrderOpenPrice())         
   }//if (OrderType()==OP_SELL)

} //End of JumpingStopLoss sub
*/
void WaitForConnection()
{
   //An attempt to make the bot hang around until all the usual criminal disconnection suspects are overcome
   while (IsTradeContextBusy() || !IsConnected() ||!IsTradeAllowed() )
   {
      Comment("");
      Comment("Criminal is pissing around with the connection. Please hang on for a brief ice age.");
   }//while (IsTradeContextBusy() || !IsConnected() ||!IsTradeAllowed() )   
   
}//End void WaitForConnection()



void LookForOpenTrades()
{
   //Searches for open trades
   TradeOpen = false;
   TicketNo = 0;
   
   
   if (OrdersTotal() == 0) return; //nothing to do
   
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderMagicNumber() == MagicNumber && OrderSymbol() == Symbol() ) 
      {
         if (OrderType() == OP_BUY || OrderType() == OP_SELL)
         {
            TicketNo = OrderTicket();
            TradeOpen = true;
            return;
         }//if (OrderType() == OP_BUY || OrderType() == OP_SELL)
         
         
      }//if (OrderMagicNumber() == MagicNumber && OrderSymbol() == symbol)       
   }//for (int cc = OrdersTotal() - 1; cc >= 0, cc--)
   

   
   
}//End void LookForOpenTrades()

bool NewsFilterCheck()
{
   // Checks for impending news events.
   // Deletes pending trades where necessary.
   // Closes open trades in profit or at be if required.
   // Returns true if news is inside the user parameters, else false

   
   if(!IsTesting())
   {      
      int  minutesUntilNextEvent = iCustom(NULL, 0, "FFCal", true, true, false, true, true, 1, 1);
      datetime dTime = minutesUntilNextEvent * 60;
      string sTime = TimeToStr(dTime, TIME_MINUTES);
      string sText;
      
      if (minutesUntilNextEvent>MinsUntilNews)//No news within the chosen timescale
      {
         sText = StringConcatenate("No News within the next ", sTime);
         bool TradeAllowed = true;
      }//if (minutesUntilNextEvent>MinsUntilNews)
      else
      {
         //News event within the chosen timescale
         int impactOfNextEvent = iCustom(NULL, 0, "FFCal", true, true, false, true, true, 2, 1);
         string sImpact = Num2Impact(impactOfNextEvent);
         if(StringLen(sImpact)>0) sImpact = "[" + sImpact + "] ";
         //sText = sImpact + "News in " + minutesUntilNextEvent + " mins.";
         sText = sImpact + "News in " + sTime;
         ScreenMessage = StringConcatenate(ScreenMessage, Gap, sText, NL);
         //Should the robot suspend trading?
         if (impactOfNextEvent >= NewsImpact)
         {
            TradeAllowed = false;//Suspend trading            
         }//if (impact >= NewsImpact)
         
      }//else
      ScreenMessage = StringConcatenate(ScreenMessage, Gap, sText, NL);
      return(TradeAllowed);
   }//if(!IsTesting())


}// End bool NewsFilterCheck()

string Num2Impact(int impact)
{
 if (impact == 3) return ("HIGH IMPACT");
 if (impact == 2) return ("MED IMPACT");
 if (impact == 1) return ("LOW IMPACT");
 else return ("");
}//End string Num2Impact(int impact)

void GetSpread()
{
   Spread = MarketInfo(Symbol(), MODE_SPREAD);
}//End void GetSpread()


void GetSmaTradeDirection()
{
   //Sets TradeDirection according to the market in relation to the two sma's
   TradeDirection = none;
   
   Ema = iMA(NULL, 0, 20, 0, MODE_EMA, PRICE_CLOSE, 0);
   
   
   
   //Check there are at least 10 pips in favour of the trade direction
   if (Ask > Ema) 
   {
      if (Ask - Ema > MinBreakPips * Point) TradeDirection = long;
   }//if (Ask > Ema && Ask > sma100) 
   
   
   if (Bid < Ema)
   {
      if (Ema - Bid > MinBreakPips * Point) TradeDirection = short;
   }//if (Bid < Ema && Bid < sma100) TradeDirection = short;
   

}//void GetSmaTradeDirection()

void GetMacdDirection()
{
   //Returns long if macd has crossed into positive within the last 5 Bars
   //Returns short if macd has crossed into negative within the last 5 Bars
   //Returns none if neither
   
   MacdDirection = none;
   MacdVal = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 0) -
             iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_SIGNAL, 0);

   if (MacdVal > 0)
   {
      for (int cc = 1; cc < 5; cc++)
      {
         double PrevMacdVal = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, cc) -
                       iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_SIGNAL, cc);
         
         if (PrevMacdVal < 0)
         {
            MacdDirection = long;
            return;
         }//if (MacdVal < 0)
         
      }//for (int cc = 1; cc < 4: cc ++)
   }//if (MacdVal > 0)
   
   
   if (MacdVal < 0)
   {
      for (cc = 1; cc < 5; cc++)
      {
         PrevMacdVal = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, cc) -
                       iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_SIGNAL, cc);
         
         if (PrevMacdVal > 0)
         {
            MacdDirection = short;
            return;
         }//if (MacdVal < 0)         
      }//for (int cc = 1; cc < 4: cc ++)
   }//if (MacdVal < 0)
   
   
   

}//End void GetMacdDirection()

void ShouldHalfTradeClose()
{
   //Only called if selected trade is in profit/
   //Closes half the trade at profit of risk x 2
   
   //Long
   if (OrderType() == 0)
   {
      double HcPrice = NormalizeDouble(OrderOpenPrice() + (OrderOpenPrice() - OrderStopLoss()) * 2, Digits);//Half close price
      if (Ask > HcPrice)
      {
        bool result = OrderClose(OrderTicket(),OrderLots() / 2, OrderClosePrice(),100,CLR_NONE);
        if (!result)
        {
             int err=GetLastError();
             Alert(Symbol(), " MA MACD Combo robot ", OrderType()," part-close failed with error(",err,"): ",ErrorDescription(err));
             return;
        }//if (!result)
        //Get new ticket number
        Sleep(100);
        LookForOpenTrades();
        OrderSelect(TicketNo, SELECT_BY_TICKET);
        if (OrderStopLoss() < OrderOpenPrice() )
        {
           double SL = OrderOpenPrice();
           result = OrderModify(OrderTicket(), OrderOpenPrice(), SL, OrderTakeProfit(), 0, CLR_NONE);
           if (!result)
            {
                err=GetLastError();
                Alert(Symbol(), " MA MACD Combo robot ", OrderType(), " Stop loss move failed with error(",err,"): ",ErrorDescription(err));
                return;
            }//if (!result)     
        }//if (OrderStopLoss() < OrderOpenPrice() )
     }//if (Ask > HcPrice)      
   }//if (OrderType() == 0)
   
   //Short
   if (OrderType() == 1)
   {
      HcPrice = NormalizeDouble(OrderOpenPrice() - (OrderStopLoss() - OrderOpenPrice()) * 2, Digits);//Half close price
      if (Bid < HcPrice)
      {
         result = OrderClose(OrderTicket(),OrderLots() / 2, OrderClosePrice(),100,CLR_NONE);
         if (!result)
         {
             err=GetLastError();
             Alert(Symbol(), " MA MACD Combo robot ", OrderType()," part-close failed with error(",err,"): ",ErrorDescription(err));
             return;
         }//if (!result)
        //Get new ticket number
        Sleep(100);
        LookForOpenTrades();
        OrderSelect(TicketNo, SELECT_BY_TICKET);
        if (OrderStopLoss() < OrderOpenPrice() )
        {
           SL = OrderOpenPrice();
           result = OrderModify(OrderTicket(), OrderOpenPrice(), SL, OrderTakeProfit(), 0, CLR_NONE);
           if (!result)
            {
                err=GetLastError();
                Alert(Symbol(), " MA MACD Combo robot ", OrderType(), " Stop loss move failed with error(",err,"): ",ErrorDescription(err));
                return;
            }//if (!result)     
        }//if (OrderStopLoss() < OrderOpenPrice() ) 
      }//if (Bid < HcPrice)      
   }//if (OrderType() == 1)
   

}//void ShouldHalfTradeClose()

bool ShouldRobotSleep()
{
   // Checks the history list to find a closed trade.
   // If one exists, checks to see if it closed more than SleepAfterTradeClosesMins.
   // Returns false (sleep not needed) if so, else true (sleep needed)
   
   if (OrdersHistoryTotal() == 0) return(false);// No history trades, so sleep clearly not needed
   
   for(int cnt=0; cnt<OrdersHistoryTotal(); cnt++)
   {
      if(!OrderSelect(cnt,SELECT_BY_POS,MODE_HISTORY)) continue;
      {       
         if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
         {
            int TimePassed = (TimeCurrent() - OrderCloseTime()) / 60;
            if (TimePassed < SleepAfterTradeClosesMins) return(true);//Robot should sleep
         }//if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)            
      }//if(!OrderSelect(cnt,SELECT_BY_POS,MODE_HISTORY))
   }//for(int cnt=0; cnt<OrdersHistoryTotal(); cnt++)

   //Got this far, so sleep not needed
   return(false);

}//bool ShouldRobotSleep()

void AdjustFor4digitCriminal()
{

   if (Digits == 2 || Digits == 4)
   {
      //JumpingStopPips/= 10;
      //BreakEvenProfit/= 10;
      //PipsAwayFromVisualJS/= 10;
      PipsAwayFromVisualTS/= 10;
      MaxSpread/= 10;
      MinBreakPips/= 10;
      ConservativeSlPips/= 10;
      //MinStopLoss/= 10;
   }//if (Digits == 2 || Digits == 4)

}//void AdjustFor4digitCriminal()

void TrailingStopLoss()
{
      
   if (!OrderSelect(TicketNo, SELECT_BY_TICKET) ) return;
   if (OrderCloseTime() > 0) return;
   
   //Only trail after be
   if (OrderType() == OP_BUY && OrderStopLoss() < OrderOpenPrice() ) return;
   if (OrderType() == OP_SELL && OrderStopLoss() > OrderOpenPrice() ) return;
   
   double TrailingStopPips = 150;
   if (Digits == 2 || Digits == 4) TrailingStopPips/= 10;
   
   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
		          result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
               if (result)
               {
                  Print("Trailing stop updated: ", OrderSymbol(), ": SL ", sl, ": Ask ", Ask);
               }//if (result) 
               else
               {
                  int err=GetLastError();
                  Print(Symbol(), " Buy order modify failed with error(",err,"): ",ErrorDescription(err) );
               }//else
   
		       }//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
		            result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
                  if (result)
                  {
                     Print("Trailing stop updated: ", OrderSymbol(), ": SL ", sl, ": Bid ", Bid);
                  }//if (result)
                  else
                  {
                     err=GetLastError();
                     Print(Symbol(), " Sell order modify failed with error(",err,"): ",ErrorDescription(err));
                  }//else
    
		       }//if (Ask < sl -  (TrailingStopPips*Point))
		   }//if (Ask <= OrderOpenPrice() - (TrailingStopPips*Point))
      }//if (OrderType()==OP_SELL) 

   /*
   //Calculate trailing stop pips 
   double TrailingStopPips;
   double PipsAway = 15;
   if (Digits == 3 || Digits == 5) PipsAway*=10;
   
   int multiplier;
   if (Digits == 2) multiplier = 100;
   if (Digits == 3) multiplier = 1000;
   if (Digits == 4) multiplier = 10000;
   if (Digits == 5) multiplier = 100000;

   if (OrderType() == 0)
   {
      int method;
      if (OrderOpenPrice() >= Ema) TrailingStopPips = OrderOpenPrice() - NormalizeDouble(OrderOpenPrice() - (PipsAway * Point),Digits) * multiplier; method = 1;
      if (OrderOpenPrice() < Ema) TrailingStopPips = NormalizeDouble(Ema - (Ema - (PipsAway * Point)), Digits) * multiplier; method = 2;
   }//if (OrderType() == 0)
   
   if (OrderType() == 1)
   {
      if (OrderOpenPrice() <= Ema) TrailingStopPips = NormalizeDouble(OrderOpenPrice() + (PipsAway * Point),Digits) - OrderOpenPrice() * multiplier;
      if (OrderOpenPrice() > Ema) TrailingStopPips = NormalizeDouble(Ema + (PipsAway * Point) - Ema, Digits) * multiplier;
   }//if (OrderType() == 1)
   */

      
} // End of TrailingStopLoss()

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{

   if (RobotDisabled )
   {
      Comment("The robot has been suspended. Reason: ", DisabledMessage);
      return;
   }//if (RobotDisabled )

   //Adjust settings for 4 digit crim.
   //Moved from init() to here, to defeat those crims who appear to mucking around with their quote digits (problem
   //first cropped up in the scooby-doo robots thread)
   AdjustFor4digitCriminal();

      
   //Check for open trade. Ticket number is stored in TicketNo
   LookForOpenTrades();
   
   
   //Check for sleep time after trade closure for any reason
   if (!TradeOpen)
   {
      bool SendToSleep = ShouldRobotSleep();// Compares closure time of history trade with current time, 
                                            // returning true for sleep or false. Will return false if no history trades
      if (SendToSleep)
      {
         Comment("Sleeping after trade closure");
         Sleep((SleepAfterTradeClosesMins*60)*1000);
      }//if (SendToSleep)
      
   }//if (!TradeOpen && !ShortOpen)
   
   
   
   ////////////////////////////////////////////////////////////////////////////////////////////
   //Stop loss manipulation
   /*
   if (JumpingStop)
   {
      if (TradeOpen)
      {
         JumpingStopLoss(TicketNo);
      }//if (TradeOpen)      
   }//if (JumpingStop)
   */
   
   //Partial trade closure
   if (TradeOpen)
   {
      OrderSelect(TicketNo, SELECT_BY_TICKET);
      if (OrderCloseTime() == 0 && OrderProfit() > 0)
      {
         if (OrderLots() == Lot) ShouldHalfTradeClose();
         TrailingStopLoss();
      }//if (OrderCloseTime() == 0 && OrderProfit() > 0)      
   }//if (TradeOpen)
   
      
   ////////////////////////////////////////////////////////////////////////////////////////////
   
   //Only allow one open trade at a time
   if (TradeOpen)
   {
      DisplayUserFeedback();
      return;
   }//if (TradeOpen || ShortOpen)
   
   
   bool TradeAllowed = true;
   //Trade entry. Check overriding filters first
   if (UseNewsFilter)
   {
      TradeAllowed = NewsFilterCheck();
      if (!TradeAllowed)
      {
         DisplayUserFeedback();
         return;
      }//if (!TradeAllowed)
   }//if (UseNewsFilter)
   
   
   //Overriding filters ok, so continue
   GetSmaTradeDirection();//Looks at market compared to sma's and sets TradeDirection accordingly - none, long or short
   if (TradeDirection == none) TradeAllowed = false;
   
   //Check macd. 
   //Will return long if macd crossed into positive within the last 5 bars.
   //Will return short if macd crossed into negative within the last 5 bars.
   GetMacdDirection();
   
   //Cut all this short if trading is not allowed
   if (!TradeAllowed)
   {
      DisplayUserFeedback();
      return;
   }//if (!TradeAllowed)
   
   if (MacdDirection == none) TradeAllowed = false;
   
   if (TradeAllowed)
   {
      if (TradeDirection == long && MacdDirection == long && LongTradeAllowed)
      {
         SendSingleTrade(0);
      }//if (Ask - HighestSma > 10 * Point) TradeDirection = long;
      
      if (TradeDirection == short && MacdDirection == short && ShortTradeAllowed)
      {
         SendSingleTrade(1);
      }//if (Ask - HighestSma > 10 * Point) TradeDirection = long;
      
      
   
   }//if (TradeAllowed)
   
   
   ////////////////////////////////////////////////////////////////////////////////////////////
   
  
   DisplayUserFeedback();
  
   
}
//+------------------------------------------------------------------+