//+------------------------------------------------------------------+
//|                   Scooby-doo Multi-Rsi Multi-Lot trading robot.mq4|
//|                                  Copyright © 2009, Steve Hopwood |
//|                              http://www.hopwood3.freeserve.co.uk |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Steve Hopwood"
#property link      "http://www.hopwood3.freeserve.co.uk"
#include <WinUser32.mqh>
#include <stdlib.mqh>
#define  NL    "\n"
#define  up "Up"
#define  down "Down"
#define  none "None"

/*
   for (int cc = OrdersTotal(); cc >= 0 ; cc--)
   {
      if (!OrderSelect(cc,SELECT_BY_POS)) continue;
      if (OrderMagicNumber()==MagicNumber)      
      {
            
      }//if (OrderMagicNumber()==MagicNumber)
   }//for (int cc=0; cc<OrdersTotal(); cc++)

Go Short

- Wait for 2TF RSI > 70 Sell 1.0 Lot
- Wait for 2TF RSI > 80 Sell 2.0 Lot
- Wait for 2TF RSI > 90 Sell 3.0 Lot
- Close out when TP hit

Go Long

- Wait for 2TF RSI < 30 Sell 1.0 Lot
- Wait for 2TF RSI < 20 Sell 2.0 Lot
- Wait for 2TF RSI < 10 Sell 3.0 Lot
- Close out when TP hit

Your starting lotsize should be AccountFreeMargin() / 50000. The sequence should only start when the currency pair first becomes OB or OS.

void DisplayUserFeedback()
void DoesTradeExist()
void SendSingleTrade(int type, string comment, double lotsize)
void ReadRsi()
void ManageTrade()
void DoesTradeNeedHedging()
void ManageHedgedPosition()
bool CloseBasket()

*/

extern string           gen="----General----";
extern double           Lot=0.02;
extern bool             RobotCalculatesLotSize=true;
extern int              LotDivisor=50000;
extern int              StopLoss=300;
extern bool             HedgeNotStopLoss=true;
extern double           BreakEvenProfitPercent=0.1;
extern int              TakeProfitPercentage=1;
extern int              MagicNumber=833645;
extern string           TradeComment="MTFML";
extern bool             CriminalIsECN=false;
extern string           tt="----Trading hours----";
extern int              TradeHourStart=0;
extern int              TradeHourStop=24;
extern string           sls="----Trade management----";
extern bool             EaManagesTrades=false;
extern bool             HideStopLossEnabled=false;
extern int              HiddenStopLossPips=200;
extern bool             HideTakeProfitEnabled=false;
extern int              HiddenTakeProfitPips=200;
extern string           JSL="Jumping stop loss";
extern bool             JumpingStop=false;
extern int              JumpingStopPips=300;
extern bool             AddBEP=true;
extern int              BreakEvenProfit=20;
extern bool             HideJumpingStop=false;
extern int              PipsAwayFromVisualJS=100;
extern string           TSL="Trailing stop loss";
extern bool             TrailingStop=false;
extern int              TrailingStopPips=500;
extern bool             HideTrailingStop=false;
extern int              PipsAwayFromVisualTS=100;
extern string           oae="----Odds and ends----";
extern int              DisplayGapSize=30;


//Trading
double                  BasketTakeProfit;
double                  BasketUpl;
bool                    Trade1Open;
bool                    Trade2Open;
bool                    Trade3Open;
bool                    ForceBasketClosure;

//RSI variablew
double                  Rsi;

//Hedging
bool                    TradeExists;
bool                    HedgeExists;
string                  HedgeComment="Hedge";
bool                    TicketNo;
bool                    HedgeTicketNo;

//Misc stuff
string                  ScreenMessage, Gap;
bool                    RobotDisabled;
string                  DisabledMessage;

void DisplayUserFeedback()
{
//double                  D01, H04, H01, M15;
     
   ScreenMessage = "";
   
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Rsi = ", Rsi, NL);
   
   if (RobotCalculatesLotSize) ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Robot is calculating the lot size (LotDivisor = ", LotDivisor, ")", NL);   
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Lot size = ", Lot, NL);
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, "BasketTakeProfit = ", DoubleToStr(BasketTakeProfit, 2), " (TakeProfitPercentage = ", TakeProfitPercentage, "%)", NL);
   if (HedgeNotStopLoss)
   {
      double bep = AccountBalance() * (BreakEvenProfitPercent / 100);
      ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Hedging is enabled.");
      ScreenMessage = StringConcatenate(ScreenMessage, "  BreakEvenProfitPercent = ",BreakEvenProfitPercent, " (", DoubleToStr(bep,2), ")",NL);
   }//if (HedgeNotStopLoss)
   else ScreenMessage = StringConcatenate(ScreenMessage, Gap, "StopLoss = ", StopLoss, NL);
   if (CriminalIsECN) ScreenMessage = StringConcatenate(ScreenMessage, Gap, "CriminalIsECN = true          ", NL);
   else ScreenMessage = StringConcatenate(ScreenMessage, Gap, "CriminalIsECN = false          ", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Magic number = ", MagicNumber, NL);
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Trade comment = ", TradeComment, NL);
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, "TradeHourStart = ", TradeHourStart, NL);
   ScreenMessage = StringConcatenate(ScreenMessage, Gap, "TradeHourStop = ", TradeHourStop, NL);
   if (EaManagesTrades)
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, Gap, "Management features:");
      if (HideStopLossEnabled)
      {
        ScreenMessage = StringConcatenate(ScreenMessage, NL, Gap, "Hidden stop loss is enabled. Hidden stop = ", HiddenStopLossPips, "pips");
      }//if (HideStopLossEnabled)
   
      if (HideTakeProfitEnabled)
      {
        ScreenMessage = StringConcatenate(ScreenMessage, NL, Gap, "Hidden take profit is enabled. Hidden stop = ", HiddenTakeProfitPips, "pips");
      }//if (HideStopLossEnabled)
        
      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");
      }
   
      if(TrailingStop==true)
      {
         ScreenMessage = StringConcatenate(ScreenMessage, NL, Gap, "Trailing stop on and set to ", TrailingStopPips);
         if (HideTrailingStop)  ScreenMessage = StringConcatenate(ScreenMessage, " (HideTrailingStop = true: PipsAwayFromVisualTS = ", PipsAwayFromVisualTS, ")");
      }
      else
      {
         ScreenMessage = StringConcatenate(ScreenMessage, NL, Gap, "Trailing stop disabled");
      }
   }//if (EaManagesTrades)   
   ScreenMessage = StringConcatenate(ScreenMessage, NL);
   if (TradeExists)
   {
      if (OrderCloseTime() == 0) ScreenMessage = StringConcatenate(ScreenMessage, NL, Gap, "Open trade upl ", DoubleToStr(BasketUpl, 2), NL);
   }//if (TradeOpen)
   if (HedgeExists)
   {
      OrderSelect(HedgeTicketNo, SELECT_BY_TICKET);
      if (OrderCloseTime() == 0) ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Open hedge trade upl ", DoubleToStr(OrderProfit(), 2), NL);
   }//if (HedgeTradeOpen)
   
   //ScreenMessage = StringConcatenate(ScreenMessage, Gap, "--", NL);
   Comment(ScreenMessage);

}//void DisplayUserFeedback()

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
//----
   
  
   //Check magic number.
   if (!IsDemo() )
   {
      if (MagicNumber == 833645)
      {
         MessageBox("You cannot run this robot until changed the MagicNumber input from the default of 833645." + 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 == 12345)
   }//if (!IsDemo)
      
   //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)



   //Adjust settings for 4 digit crim
   if (Digits == 2 || Digits == 4)
   {
      //StopLoss/= 10;
      HiddenStopLossPips/= 10;
      HiddenTakeProfitPips/= 10;
      JumpingStopPips/= 10;
      BreakEvenProfit/= 10;
      PipsAwayFromVisualJS/= 10;
      TrailingStopPips/= 10;
      PipsAwayFromVisualTS/= 10;      
   }//if (Digits == 2 || Digits == 4)
   
   
   
   Gap="";
   if (DisplayGapSize >0)
   {
      for (int cc=0; cc< DisplayGapSize; cc++)
      {
         Gap = StringConcatenate(Gap, " ");
      }   
   }

   //start();
   //return;
   
   
   
//----
   return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
//----
   
//----
   return(0);
}

void DoesTradeExist()
{
   BasketUpl = 0;
   ForceBasketClosure = false;
   Trade1Open = false;
   Trade2Open = false;
   Trade3Open = false;
   TradeExists = false;
   
   if (OrdersTotal() == 0) return(false);
   
   for (int cc = OrdersTotal(); cc >= 0 ; cc--)
   {
      if (!OrderSelect(cc,SELECT_BY_POS)) continue;
      if (OrderMagicNumber()==MagicNumber && OrderSymbol() == Symbol() )      
      {
         if (OrderComment() == TradeComment + "1")
         {
            Trade1Open = true;
            BasketUpl+= OrderProfit();
            TradeExists = true;
         }//if (OrderComment() = TradeComment;
         
         if (OrderComment() == TradeComment + "2")
         {
            Trade2Open = true;
            BasketUpl+= OrderProfit();
         }//if (OrderComment() = TradeComment;
         
         if (OrderComment() == TradeComment + "3")
         {
            Trade3Open = true;
            BasketUpl+= OrderProfit();
         }//if (OrderComment() = TradeComment;
         
         if (OrderComment() == HedgeComment)
         {
            HedgeExists = true;
            HedgeTicketNo = OrderTicket();
            BasketUpl+= OrderProfit();
         }//if (OrderComment() = TradeComment;
            
      }//if (OrderMagicNumber()==MagicNumber)
   }//for (int cc=0; cc<OrdersTotal(); cc++)

   //Does the basket need closing because the upl has hit its tp?
   if (BasketUpl >= BasketTakeProfit)
   {
      ForceBasketClosure = true;//Force a retry at each tick if a trade closure fails
      bool AllClosed = CloseBasket();
      if (AllClosed) ForceBasketClosure = false;
   }//if (BasketUpl >= TargetUpl)

}//void DoesTradeExist()


void SendSingleTrade(int type, string comment, double lotsize)
{
   // Attempts to place a trade according to type, i.e.
   // 0 = OP_BUY
   // 1 = OP_SELL
   
   // Check spread
   //if (MarketInfo(Symbol(), MODE_SPREAD) > MaxSpreadAllowed)
   //{
      //return(false);// Spread too large, so abort send
   //}//if (MarketInfo(NULL, MODE_SPREAD) > MaxSpreadAllowed)
   
   RefreshRates();
   
   // Buy trade
   if (type == 0)
   {
      double TradePrice=Ask;
      int colour = 32768;//green
      double SL = NormalizeDouble(TradePrice - (StopLoss * Point), Digits);      
   }//if (type == 0)   
   
   
   // Sell trade
   if (type == 1)
   {
      TradePrice=Bid;      
      colour = 255;//red
      SL = NormalizeDouble(TradePrice + (StopLoss * Point), Digits);      
   }//if (type == 1)
   
   if (HedgeNotStopLoss) SL = 0;
   
   int slippage = 10;
   if (Digits == 3 || Digits == 5) slippage = 100;
   
   //Non ECN crook
   if (!CriminalIsECN) int ticket = OrderSend(Symbol(),type, lotsize, TradePrice, slippage, SL, 0, comment, MagicNumber,0, colour);
   
   //Is a 2 stage criminal
   if (CriminalIsECN)
   {
      ticket = OrderSend(Symbol(),type, lotsize, TradePrice, slippage, 0, 0, comment, MagicNumber,0, colour);
	   if (SL != 0)
	   {
		   if (ticket > 0)
		   bool result = OrderModify(ticket, OrderOpenPrice(), SL, OrderTakeProfit(), 0, CLR_NONE);
		   if (!result)
		   {
		       int err=GetLastError();
             Alert(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)
   {
      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)
   
   return(true);
}//End void SendSingleTrade(type, string comment, double lotsize)



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() 
{
   // Jump sl by pips and at intervals chosen by user .
   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);
               
            }//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)
             
            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)
         {
            Print("Jumping stop set: ", OrderSymbol(), ": SL ", sl, ": Ask ", Ask);
            
         }//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 TrailingStopLoss()
{  
   bool result;
   double sl=OrderStopLoss(); //Stop loss
   double BuyStop=0, SellStop=0;
   
   if (OrderType()==OP_BUY) 
      {
         if (HideTrailingStop)
         {
            bool TradeClosed = CheckForHiddenStopLossHit(OP_BUY, PipsAwayFromVisualJS, 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(), " 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_BUY, PipsAwayFromVisualJS, 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(), " order modify failed with error(",err,"): ",ErrorDescription(err));
                  }//else
    
		       }//if (Ask < sl -  (TrailingStopPips*Point))
		   }//if (Ask <= OrderOpenPrice() - (TrailingStopPips*Point))
      }//if (OrderType()==OP_SELL) 

      
} // End of TrailingStopLoss sub

void 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)
         {
            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 (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)
         {
            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 (OrderType() == OP_SELL)
   

}//End void HiddenStopLoss()

void HiddenTakeProfit()
{
   //Called from ManageTrade if HideStopLossEnabled = true


   //Should the order close because the stop has been passed?
   //Buy trade
   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)
         {
            Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            int err=GetLastError();
            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)
   
   //Sell trade
   if (OrderType() == OP_SELL)
   {
      tp = NormalizeDouble(OrderOpenPrice() - (HiddenTakeProfitPips * Point), Digits);
      if (Ask <= tp)
      {
         result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {
            Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            err=GetLastError();
            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_SELL)
   

}//End void HiddenTakeProfit()


void ManageTrade()
{
   //Calls the trade management functions.
   //Called from start() by the trade counting routine, so the OrderSelect() has selected the trade
   
   // Hidden stop loss
   if (HideStopLossEnabled) HiddenStopLoss();
   
   // Hidden take profit
   if (HideTakeProfitEnabled) HiddenTakeProfit();
      
   if (JumpingStop) JumpingStopLoss();
   
   if (TrailingStop) TrailingStopLoss();

}//End void ManageTrade()

void ReadRsi()
{

   Rsi = iRSI(Symbol(), 0, 2, PRICE_CLOSE, 0) ;

}//void ReadRsi()

void DoesTradeNeedHedging()
{
   //Sends a hedge trade if the original upl is at or beyond the notional stop loss.
   //Function is only called if trade upl is < 0
   
   if (HedgeExists) return;
   if (!OrderSelect(TicketNo, SELECT_BY_TICKET) ) return;
   if (OrderCloseTime() > 0) return;
   
   double HedgePrice, market;
   bool  HedgeNeeded;
   
   if (OrderType() == OP_BUY)
   {
      market = Bid;
      int type = OP_SELL;
      HedgePrice = NormalizeDouble(OrderOpenPrice() - (StopLoss * Point), Digits);
      if (Bid <= HedgePrice) HedgeNeeded = true;
   }//if (OrderType() == OP_BUY)   
   if (OrderType() == OP_SELL) 
   {
      market = Ask;
      type = OP_BUY;
      HedgePrice = NormalizeDouble(OrderOpenPrice() + (StopLoss * Point), Digits);
      if (Ask >= HedgePrice) HedgeNeeded = true;
   }//if (OrderType() == OP_SELL) 
   
   if (!HedgeNeeded) return;
   
   //Send the hedge if needed
   if (HedgeNeeded)
   {
      //Make sure that there are not too many decimal places in the result of the calculation
      double MinLot = MarketInfo(Symbol(), MODE_MINLOT);   
      int decimals;
      if (MinLot >0 && MinLot < 0.1) decimals = 2;//0.01
      if (MinLot >0.09 && MinLot < 1) decimals = 1;//0.1
      if (MinLot >0.9) decimals = 0;//1   
   
      double SendLots = NormalizeDouble(Lot / 2, decimals);
      if (SendLots < MinLot) SendLots = MinLot;
      
      int ticket = OrderSend(Symbol(), type, SendLots, market, 50, 0, 0, HedgeComment, MagicNumber, Magenta);
      if (ticket < 1)//Deal with trade failure - leave the ea to try again next tick
      {        
         int err=GetLastError();
         Alert(Symbol(), "Hedge ", type," order send failed with error(",err,"): ",ErrorDescription(err));
         return;
      }//if (ticket < 1)
      HedgeTicketNo = ticket;
      HedgeExists = true;
   }//if (HedgeNeeded)
   
   //Send succeeded, so remove the stop from the original trade
   Alert("Hedge trade sent for trade no ", TicketNo);
   Print("Hedge trade sent for trade no ", TicketNo);
   //tp removal
   if (TicketNo > 0)
   {
      OrderSelect(TicketNo, SELECT_BY_TICKET);
      if (OrderTakeProfit() != 0)
      {
         bool result = false;
         while (!result)         
         {   
            result = OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), 0, 0,CLR_NONE);
            if (!result)
            {
               err=GetLastError();
               Alert(Symbol(), " OrderModify failed with error(",err,"): ",ErrorDescription(err));
               Print(Symbol(), " OrderModify failed with error(",err,"): ",ErrorDescription(err));      
               Sleep(5000);
            }//if (!result)               
            if (OrderTakeProfit() == 0) result = true;
         }//while (!result)
      }//if (OrderTakeProfit() != 0)

   }//if (TicketNo > 0)
   
   HedgeExists=true;

}//void DoesTradeNeedHedging()

void ManageHedgedPosition()
{
   //Called when two trades are open, so must be a hedge position

   
   //Can the position be closed at be?
   double BreakEvenTarget = NormalizeDouble(AccountBalance() * BreakEvenProfitPercent / 100, 2);
   OrderSelect(TicketNo, SELECT_BY_TICKET);
   double OpenTradesUpl = OrderProfit();
   OrderSelect(HedgeTicketNo, SELECT_BY_TICKET);
   OpenTradesUpl+= OrderProfit();
   
   if (OpenTradesUpl >= BreakEvenTarget)
   {         
      //Attempt to close both trades. Abort if the first close fails
      if (OrderSelect(TicketNo, SELECT_BY_TICKET) )
      {   
         bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 50, CLR_NONE);
         if (!result) return;//Don't want to close the hedge if the original trade close failed
         if (result) 
         {
            TicketNo = 0;
            TradeExists = false;
         }//if (result) 
      }//if (OrderSelect(TicketNo, SELECT_BY_TICKET) );
         
      
      //Original trade close succeeded, so attempt to close the hedge
      if (OrderSelect(HedgeTicketNo, SELECT_BY_TICKET) ) 
      {
         result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 50, CLR_NONE);
         if (result) 
         {
            HedgeTicketNo = 0;
            HedgeExists = false;
         }//if (result) 
      }//if (OrderSelect(HedgeTicketNo, SELECT_BY_TICKET) ) 
      
   }//if (OpenTradesUpl >= 0)
   
  
}//End void ManageHedgedPosition()

bool CloseBasket()
{
   //Called whenever an entire trading basket needs closing.
   //Returns true if all trades close successfully, else false
   
   bool result=true;// Set to false if a closure fails
   
   for (int cc = OrdersTotal(); cc >= 0 ; cc--)
   {
      if (!OrderSelect(cc,SELECT_BY_POS)) continue;
      if (OrderMagicNumber()==MagicNumber)      
      {
         if (OrderType()==OP_BUY)
         {
            bool ticket =OrderClose(OrderTicket(),OrderLots(), MarketInfo(OrderSymbol(), MODE_BID),100,CLR_NONE);
            if (!ticket) result=false;
            else cc++;
         }//if (OrderType()==OP_BUY)   
         
         if (OrderType()==OP_SELL)
         {
            ticket=OrderClose(OrderTicket(),OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK),100,CLR_NONE);
            if (!ticket) result=false;
            else cc++;
         }//if (OrderType()==OP_SELL)   
         Sleep(100);
      }//if (OrderMagicNumber()==MagicNumber)
   }//for (int cc=0; cc<OrdersTotal(); cc++)

   return(result);
   

}//bool CloseBasket()


//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
//----
   
   //In case a previous basket close attempt failed
   if (ForceBasketClosure)
   {
      bool AllClosed = CloseBasket();
      if (AllClosed) ForceBasketClosure = false;
      if (!AllClosed) return;
   }//if (ForceBasketClosure)

   
   if (!IsDemo())
   {
      if (RobotDisabled)
      {
         Comment("The robot has been suspended. Reason: ", DisabledMessage);
         return;
      }//if (RobotDisabled )

      if (IsTradeContextBusy() )
      {
         Comment("Trade context is busy because the criminal is too lazy, dim or both to provide a decent server. Please wait for the cretin to stop pissing around.");
         return;
      }//if (IsTradeContextBusy)
   }//if (!IsDemo)

   //Auto lot calc
   if (RobotCalculatesLotSize)
   {
      double MinLot = MarketInfo(Symbol(), MODE_MINLOT);   
      //Make sure that there are not too many decimal places in the result of the calculation
      int decimals;
      if (MinLot >0 && MinLot < 0.1) decimals = 2;//0.01
      if (MinLot >0.09 && MinLot < 1) decimals = 1;//0.1
      if (MinLot >0.9) decimals = 0;//1   
      Lot = NormalizeDouble(AccountEquity() / LotDivisor, decimals);
      if (Lot < MinLot) Lot = MinLot;
   }//if (RobotCalculatesLotSize)
   
   BasketTakeProfit = NormalizeDouble(AccountBalance() * TakeProfitPercentage / 100, 2 );
   
   //Is there a trade already open?
   DoesTradeExist();//Also calls the management features if required
   if (TradeExists)
   {
      if (TradeExists && EaManagesTrades && !HedgeExists) ManageTrade();
      OrderSelect(TicketNo, SELECT_BY_TICKET);
      if (OrderCloseTime() == 0)
      {
         if (HedgeNotStopLoss && OrderProfit() < 0 && !HedgeExists) DoesTradeNeedHedging();
      }//if (OrderCloseTime() == 0)
      
      //Manage hedged position
      if (TradeExists && HedgeExists)
      {
         ManageHedgedPosition();
      }//if (TradeExists && HedgeTradeExists)
      
      //Catch orphan hedges
      if (!TradeExists && HedgeExists)
      {
         if (OrderSelect(HedgeTicketNo, SELECT_BY_TICKET) ) 
         {
            bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 50, CLR_NONE);
            if (result) 
            {
               HedgeTicketNo = 0;
               HedgeExists = false;
            }//if (result) 
         }//if (OrderSelect(HedgeTicketNo, SELECT_BY_TICKET) )       
      }//if (!TradeExists && HedgeTradeExists)
      
            
      ReadRsi();
      DisplayUserFeedback();
      return;
   }//if (TradeExists)
      
   static int Tries = 0;
   
   //Trading hours
   if (TimeHour(TimeLocal()) < TradeHourStart || TimeHour(TimeLocal()) > TradeHourStop) 
   {
      Comment(Gap, "Trading suspended - outside trade hours");
      Tries = 0;
      return;    
   }
   
   
   ReadRsi();
   //Trading decisions
   if (Rsi >= 70 && Rsi < 80 && !Trade1Open)
   {
      SendSingleTrade(1, TradeComment + "1", Lot);
   }//if (Rsi >= 70 && Rsi < 80 && !Trade1Open)
   
   if (Rsi >= 80 && Rsi < 90 && !Trade2Open)
   {
      SendSingleTrade(1, TradeComment + "2", Lot * 2);
   }//if (Rsi >= 70 && Rsi < 80 && !Trade1Open)
   
   if (Rsi >= 90 && !Trade3Open)
   {
      SendSingleTrade(1, TradeComment + "3", Lot * 3);
   }//if (Rsi >= 70 && Rsi < 80 && !Trade1Open)
   
   
   if (Rsi <= 30 && Rsi > 20 && !Trade1Open)
   {
      SendSingleTrade(0, TradeComment + "1", Lot);
   }//if (Rsi <= 30 && Rsi > 20 && !Trade1Open)
   
   if (Rsi <= 20 && Rsi > 10 && !Trade2Open)
   {
      SendSingleTrade(0, TradeComment + "2", Lot * 2);
   }//if (Rsi <= 20 && Rsi > 10 && !Trade2Open)
   
   if (Rsi <= 10 && !Trade3Open)
   {
      SendSingleTrade(0, TradeComment + "3", Lot * 3);
   }//if (Rsi <= 10 && !Trade3Open)
   
   
   
   DisplayUserFeedback();
   
   
//----
   return(0);
}
//+------------------------------------------------------------------+