Zone Recovery Hedge V1

Author: Contact Developer
Price Data Components
Series array that contains close prices for each barSeries array that contains open time of each bar
Orders Execution
Checks for the total of open ordersIt Closes Orders by itself It automatically opens orders when conditions are reached
Indicators Used
Indicator of the average true rangeRelative strength index
Miscellaneous
It issuies visual alerts to the screen
0 Views
0 Downloads
0 Favorites
Zone Recovery Hedge V1
//+------------------------------------------------------------------+
//|                                                    Zone Hedge EA |
//|                                                       A. Sweeney |
//+------------------------------------------------------------------+

#property copyright     "Contact Developer"
#property description   "Coded by: A. Sweeney"
#property link "https://t.me/rajeevrrs"
#property strict

// inputs, RSI OB/OS levels, RSI period, RSI timeframes
// if ob/os = false and ob/os[+1] = true take the trade


//+------------------------------------------------------------------+
//| Includes and object initialization                               |
//+------------------------------------------------------------------+

enum EA_Setting {Manual, RSI_MTF};
// enum Trade_Volume {Fixed_Lot, Fixed_P

enum CLOSE_PENDING_TYPE
{
   CLOSE_BUY_LIMIT,
   CLOSE_SELL_LIMIT,
   CLOSE_BUY_STOP,
   CLOSE_SELL_STOP,
   CLOSE_ALL_PENDING
};


//+------------------------------------------------------------------+
//| Input variables                                                  |
//+------------------------------------------------------------------+

sinput string RecoverySettings; // ** ZONE RECOVERY SETTINGS **
extern int RecoveryZoneSize = 200; // Recovery Zone Size (points)
extern int TakeProfit = 200; // Take Profit (points)
input int MaxTrades = 0; // Max Trades (0 for unlimited)
input bool SetMaxLoss = false; // Max Loss after Max Trades reached?
input double MaxLoss = 0; // Max Loss after Max Trades (0 for unlimted) in deposit currency.
input bool UseRecoveryTakeProfit = true; // Use a Recovery Take Profit
input int RecoveryTakeProfit = 50; // Recovery Take Profit (points).
extern double PendingPrice = 0; // Price for pending orders

sinput string ATRHeader; // ** ATR Dynamic Zone Sizing **
input bool UseATR = false; // Use ATR?
input int ATRPeriod = 14; // ATR Period
input double ATRZoneFraction = 0.2; // Fraction of ATR to use as Recovery Zone
input double ATRTPFraction = 0.3; // Fraction or ATR to use for TP sizes
input double ATRRecoveryZone = 0.15; // Fraction of ATR to use for recovery TP.

sinput string MoneyManagement;  	// ** MONEY MANAGEMENT SETTINGS **
input double RiskPercent = 0; // Account % Initial Lot Size  (set to 0 if not used) 
input double InitialLotSize = 0.1; // Initial Lot Size (if % not used)
input double LotMultiplier = 2; // Multiplier for Lots
input double LotAdditions = 0;
sinput string CustomLotSizing; // ** CUSTOM LOT SIZES **
input double CustomLotSize1 = 0;
input double CustomLotSize2 = 0;
input double CustomLotSize3 = 0;
input double CustomLotSize4 = 0;
input double CustomLotSize5 = 0;
input double CustomLotSize6 = 0;
input double CustomLotSize7 = 0;
input double CustomLotSize8 = 0;
input double CustomLotSize9 = 0;
input double CustomLotSize10 = 0;


sinput string TimerSettings;			// **  TIMER SETTINGS **
input bool UseTimer = false; // Use a Trade Timer?
input int StartHour = 0; // Start Hour
input int StartMinute = 0; // Start Minute
input int EndHour = 0; // End Hour
input int EndMinute = 0; // End Minute
input bool UseLocalTime = false; // Use local time?

sinput string TradeSettings;    	// ** EA SETTINGS **
input EA_Setting EA_Mode= Manual;
input int RSIPeriod = 14; // RSI Period
input double OverboughtLevel = 70; //Over-bought level
input double OversoldLevel = 30; // Over-sold level
input bool UseM1Timeframe = true; // Use M1 Timeframe?
input bool UseM5Timeframe = false; // Use M5 Timeframe?
input bool UseM15Timeframe = false; // Use M15 Timeframe?
input bool UseM30Timeframe = false; // Use M30 Timeframe?
input bool UseH1Timeframe = false; // Use H1 Timeframe?
input bool UseH4Timeframe = false; // Use H4 Timeframe?
input bool UseDailyTimeframe = false; // Use Daily Timeframe?
input bool UseWeeklyTimeframe = false; // Use Weekly Timeframe?
input bool UseMonthlyTimeframe = false; // Use Monthly Timeframe?

sinput string Visuals; // ** VISUALS **
input color profitLineColor = clrLightSeaGreen;
input int Panel_X = 40; // Panel X coordinate.
input int Panel_Y = 40; // Panel Y coordinate.
input color Panel_Color = clrBlack; // Panel background colour.
input color Panel_Lable_Color = clrWhite; // Panel lable text color.

sinput string BacktestingSettings; // ** OTHER SETTINGS **
input int MagicNumber = 141020; // Magic Number
input int Slippage = 100; // Slippage Max (Points).
input bool TradeOnBarOpen = true; // Trade on New Bar?
input int speed = 500; // Back tester speed
input double TestCommission = 7; // Back tester simulated commission


//+------------------------------------------------------------------+
//| Global variable and indicators                                   |
//+------------------------------------------------------------------+

#define EA_NAME "RRS Zone Recovery Hedge"
#define SELL_BUTTON "Sell Button"
#define BUY_BUTTON "Buy Button"
#define PENDING_EDIT "Pending Edit"
#define CLOSE_ALL_BUTTON "Close All Button"
#define TP_EDIT "TP Edit"
#define ZONE_EDIT "Zone Edit"
string gTradingPanelObjects[100];
#define PROFIT_LINE "Profit Line"

datetime gLastTime;
int gInitialTicket;
double gBuyOpenPrice;
double gSellOpenPrice;
double gBuyTakeProfit;
double gSellTakeProfit;
double gLotSize;
double gInitialLotSize;
double gInitialProfitTarget;
bool gRecoveryInitiated;
int gBuyStopTicket = 0;
int gSellStopTicket = 0;
int gBuyTicket = 0;
int gSellTicket = 0;
double gCustomLotSizes[10]; 

double UsePip;
double UseSlippage;
double gCurrentDirection;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+

int OnInit()
{
   gRecoveryInitiated = false;
   gCurrentDirection = 0;
   // Set magic number
   UsePip = PipPoint(Symbol());
   UseSlippage = GetSlippage(Symbol(), Slippage);
   gLastTime = 0;
   gCustomLotSizes[0] = CustomLotSize1;
   gCustomLotSizes[1] = CustomLotSize2;
   gCustomLotSizes[2] = CustomLotSize3;
   gCustomLotSizes[3] = CustomLotSize4;
   gCustomLotSizes[4] = CustomLotSize5;
   gCustomLotSizes[5] = CustomLotSize6;
   gCustomLotSizes[6] = CustomLotSize7;
   gCustomLotSizes[7] = CustomLotSize8;
   gCustomLotSizes[8] = CustomLotSize9;
   gCustomLotSizes[9] = CustomLotSize10;
 
   CreateTradingPanel();
   Print("INIT SUCCESFUL, Recovery Initiated: ", gRecoveryInitiated, " Current Dirn: ", gCurrentDirection, " Magic No: ", MagicNumber, " Slippage: ", Slippage);
   
   if(OrdersTotal() > 0) FindOpenOrders();
       
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert Shutdown function                                             |
//+------------------------------------------------------------------+

void OnDeinit(const int reason)
{
   switch(reason)
   {
      case 0:
      {
         DeleteTradePanel();
         Print("EA De-Initialised, removed by EA");
         break;
      }
      case 1:
      {
         DeleteTradePanel();
         Print("EA De-Initialised, removed by user");
         break;
      }
      case 2:
      {
         DeleteTradePanel();
         Print("EA De-Initialised, EA recompiled");
         break;
      }
      case 3:
      {
         DeleteTradePanel();
         Print("EA De-Initialised, Symbol changed");
         break;
      }   
      case 4:
      {
         DeleteTradePanel();
         Print("EA De-Initialised, chart closed by user.");
         break;
      }
      case 5:
      {
         Print("EA De-Initialised, input parameters changed.");
         break;
      }
      case 6:
      {
         Print("EA De-Initialised, account changed");
         break;
      }
      case 7:
      {
         DeleteTradePanel();
         Print("EA De-Initialised, A new template has been applied.");
         break;
      }
      case 8:
      {
         DeleteTradePanel();
         Print("EA De-Initialised, EA failed to initialize.");
         break;
      }
      case 9:
      {
         DeleteTradePanel();
         Print("EA De-Initialised, Terminal closed by user.");
         break;
      }  
   }
}



//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+

void OnTick()
{
   if(IsVisualMode() == true)
   {
      int Waitloop = 0;
      while(Waitloop < speed)
      {
         Waitloop++;
      }
   }
   // Check timer
   bool tradeEnabled = true;
   if(UseTimer == true)
   {
      tradeEnabled = CheckDailyTimer();
   }
   
   // Check for bar open
   bool newBar = true;
   int barShift = 0;
   
   // check if a new bar has been opened
   if(TradeOnBarOpen == true)
   {
      newBar = false;
      datetime time[];
      bool firstRun = false;
      
      CopyTime(_Symbol,PERIOD_CURRENT,0,2,time);
      
      if(gLastTime == 0) firstRun = true;
	
	   if(time[0] > gLastTime)
	   {
		   if(firstRun == false) newBar = true;
		   gLastTime = time[0];
	   }
      barShift = 1;
   }
   
   // Money management
   
   // set lot size to initial lot size for doubling later
   gInitialLotSize = CheckVolume(_Symbol, InitialLotSize); // check the input value for lot initial lot size and set to initial
   
   if(RiskPercent != 0)
   {
      int StopLoss = TakeProfit;
      if(UseATR == true)
      {
         double atr = iATR(_Symbol, PERIOD_D1, ATRPeriod, 1);
         StopLoss = round((atr*ATRTPFraction)/_Point); // set the stop loss a fraction of atr in points
      }
      gInitialLotSize = GetTradeSize(_Symbol,InitialLotSize,RiskPercent,StopLoss);
   }

   // Check entries on new bar
   if(newBar == true && tradeEnabled == true) // check for new bar and whether timer allows to open
   {
      
      switch(EA_Mode)
      {
         case RSI_MTF:
         {
            int direction = Is_RSI_OBOS_on_MTF(barShift + 1);
            int nowFalse = Is_RSI_OBOS_on_MTF(barShift);
            if(direction == 1 && nowFalse == 0)
            {
               Print("Buy signal generated.");
               if(gCurrentDirection == 0)
               {
                  TakeTrade(direction);
                  Print("Buy signal generated.");
               } else {
                  Print("Buy signal not used as EA in trade on ", _Symbol);
               }
            }
            else if(direction == -1 && nowFalse == 0)
            {
               if(gCurrentDirection == 0) 
               {
                  TakeTrade(direction);
                  Print("Sell signal generated.");
               } else {
                  Print("Sell signal not used as EA in trade on ", _Symbol);
               }
            }
         }              
      }
   }   
   
   

   if(gCurrentDirection != 0)
   {
      // on every tick work out the average price
      // count the number of buy and sell orders
      int positions = 0;
      double averagePrice = 0;
      double currentProfit = 0;
      double positionSize = 0;
      double netLotSize = 0;
      double totalCommision = 0;
      double totalSpreadCosts = 0;
      double point_value = _Point*MarketInfo(_Symbol, MODE_TICKVALUE)/MarketInfo(_Symbol, MODE_TICKSIZE);
   
      for(int counter = 0; counter <= OrdersTotal() - 1; counter++)
      {
         if(OrderSelect(counter, SELECT_BY_POS))
         {
            if(OrderMagicNumber() == MagicNumber && OrderSymbol() == Symbol())
            {
               positions += 1;
               currentProfit += OrderProfit();
               
               if(OrderType() == OP_BUY)
               {
                  positionSize += (OrderOpenPrice()*OrderLots());
                  netLotSize += OrderLots();
                  totalSpreadCosts += (OrderLots()*MarketInfo(_Symbol, MODE_SPREAD)*point_value);
                  totalCommision += OrderCommission();
               }
               else if(OrderType() == OP_SELL)
               {
                  positionSize -= (OrderOpenPrice()*OrderLots());
                  netLotSize -= OrderLots();
                  totalSpreadCosts += (OrderLots()*MarketInfo(_Symbol, MODE_SPREAD)*point_value);
                  totalCommision += OrderCommission();
               }
            }
         }
      }

      // if the current profits are greater than the desired recovery profit and costs close the trades
      double volume;
      if(CustomLotSize1 != 0) volume = CustomLotSize1;
      else volume = gInitialLotSize;
      double profitTarget = RecoveryTakeProfit*point_value*volume;
      if(UseATR == true) 
      {
         double atr = iATR(_Symbol, PERIOD_D1, ATRPeriod, 1);
         profitTarget = (ATRRecoveryZone*atr*point_value*volume)/_Point;
      }
      
      // simulate commission for backtesting
      double tradeCosts = 0;
      if(IsTesting())
      {
         tradeCosts = totalSpreadCosts+(MathAbs(netLotSize)*TestCommission);
      } else {
         tradeCosts = totalSpreadCosts+totalCommision; // spread and commision
      }
     
      double tp = RecoveryTakeProfit;
      if(UseRecoveryTakeProfit == false || gRecoveryInitiated == false)
      {
         profitTarget = TakeProfit*point_value*volume; // initial profit is equal to planned rz over tp, in $$
      }
      
      if(currentProfit >= (profitTarget +tradeCosts))
      {
         CloseOrdersAndReset();
         Print("Orders closed, profit target of: ", DoubleToStr(profitTarget, 2), "$ exceeded at: ", DoubleToStr(currentProfit, 2), "$, Costs(", DoubleToStr(tradeCosts, 2), "$)");        
      }
      if(netLotSize != 0)
      {
         averagePrice = NormalizeDouble(positionSize/netLotSize, _Digits);
         Comment(StringConcatenate("Average Price: ", DoubleToStr(averagePrice, _Digits), ", Profit Target: $", DoubleToStr(profitTarget, 2), " + Trade Costs: $", DoubleToStr(tradeCosts, 2), ", Running Profit:  $", DoubleToStr(currentProfit, 2)));
      }
      
      if(positions >= MaxTrades && MaxTrades != 0 && currentProfit < -MaxLoss && SetMaxLoss == true)
      {
         CloseOrdersAndReset();
         Print("Orders closed, max trades reached and max loss of: -$", MaxLoss, " by $", currentProfit);
      }   
   
      // set the take profit line price
      if(gCurrentDirection == 1 && netLotSize != 0)
      {
         tp = (profitTarget + tradeCosts - currentProfit)*_Point/(point_value*netLotSize);
         double   profitPrice = NormalizeDouble(Bid + tp, _Digits);
         if(!ObjectSetDouble(0, PROFIT_LINE, OBJPROP_PRICE, profitPrice)) Print("Could not set line");
      } else if(gCurrentDirection == -1 && netLotSize != 0) {
         tp = (profitTarget + tradeCosts - currentProfit)*_Point/(point_value*netLotSize);   
         double   profitPrice = NormalizeDouble(Ask + tp, _Digits);
         if(!ObjectSetDouble(0, PROFIT_LINE, OBJPROP_PRICE, profitPrice)) Print("Could not set line");   
      } 
      

   
   // check if the current direction is buy and the bid price (sell stop has opened) is below the recovery line
      if(gCurrentDirection == 1)
      {
         double price = MarketInfo(Symbol(), MODE_ASK);
         if(OrderSelect(gSellStopTicket, SELECT_BY_TICKET))
         {
            if(OrderType() == OP_SELL) // if the sell stop has opened
            {
               Print("Recovery Sell Stop has been opened, initiating recovery...");
               gSellTicket = gSellStopTicket; // make the stop a sell ticket
               gSellStopTicket = 0; // reset the sell stop ticket
               
               // increase the lot size 
               gLotSize = GetTradeVolume(positions+1);

               if(MaxTrades == 0 || positions < MaxTrades) // check we've not exceeded the max trades
               {
                 // open a buy stop order at double the running lot size
                 gBuyStopTicket = OpenPendingOrder(Symbol(), OP_BUYSTOP, gLotSize, gBuyOpenPrice, 0, 0, StringConcatenate("Recovery Buy Stop opened."), 0, clrTurquoise); // create an opposite buy stop
                 gRecoveryInitiated = true; // signal that we are in recovery mode
               }
               // change the current direction to sell
               gCurrentDirection = -1;            
            }
         } else {
            string message = "Warning - EA could not find the recovery Sell Stop";
            Alert(message);
            Print(message);
         }
      }
   // check if the current direction is sell and the ask price (sell stop has opened) is below the recovery line
      if(gCurrentDirection == -1)
      {
         double price = MarketInfo(Symbol(), MODE_BID);   
         if(OrderSelect(gBuyStopTicket, SELECT_BY_TICKET))
         {
            if(OrderType() == OP_BUY) // if the buy stop has opened
            {
               Print("Recovery Buy Stop has been opene, initiating recovery...");
               gBuyTicket = gBuyStopTicket; // set the buy ticket to the stop
               gBuyStopTicket = 0; // reset the buy ticket
               
               // increase the lot size
               gLotSize = GetTradeVolume(positions+1);               
               
               if(MaxTrades == 0 || positions < MaxTrades) // check we've not exceeded the max trades
               {
                  // open a sell stop order at double the running lot size
                  gSellStopTicket = OpenPendingOrder(Symbol(), OP_SELLSTOP, gLotSize, gSellOpenPrice, 0, 0, StringConcatenate("Recovery Sell Stop opened."), 0, clrPink); // create an opposite sell stop
                  gRecoveryInitiated = true; // signal we're in recovery mode
               }
               // change the current direction to sell
               gCurrentDirection = 1;
            }
         } else {
            string message = "Warning - EA could not find the recovery Buy Stop";
            Alert(message);
            Print(message);
         }
      }
   } else {
      Comment("No OGT Zone Recovery Trades Active");
   }
}

// Initial trade taking algorithm

void TakeTrade(int direction)
{

    double tp = 0;
    double rz = 0;
    // if the user has selected to use the ATR to size zones
    if(UseATR == true)
    {
      double atr = iATR(_Symbol, PERIOD_D1, ATRPeriod, 1);
      tp = atr*ATRTPFraction;
      rz = atr*ATRZoneFraction;
      //TakeProfit = tp;
      //RecoveryZoneSize = rz;
    } else if(UseATR == false)
    {
      tp = TakeProfit*_Point; // tp as price units
      rz = RecoveryZoneSize*_Point; // rz as price
    }
    if(CustomLotSize1 != 0) gLotSize = CustomLotSize1;
    else gLotSize = gInitialLotSize;

    double price = 0;
    
   if(direction == 1)
   {
   
       gBuyTicket = OpenMarketOrder(Symbol(), OP_BUY, gLotSize, "Initial Buy Order", clrGreen);
       if(OrderSelect(gBuyTicket, SELECT_BY_TICKET))
       {                 
          gBuyOpenPrice = OrderOpenPrice();       
          gSellOpenPrice = NormalizeDouble((gBuyOpenPrice - rz), _Digits);
          gBuyTakeProfit = NormalizeDouble((gBuyOpenPrice + tp), _Digits);
          gSellTakeProfit = NormalizeDouble((gBuyOpenPrice - (tp + rz)), _Digits);
          
          // ModifyStopsByPrice(gBuyTicket, gSellTakeProfit, gBuyTakeProfit);  
      
          //open a recovery stop order in the opposite direction
          gLotSize = GetTradeVolume(2);
          gSellStopTicket = OpenPendingOrder(Symbol(), OP_SELLSTOP, gLotSize, gSellOpenPrice, 0, 0, "Initial Recovery Sell Stop)", 0, clrPink);
          gCurrentDirection = direction;
          price = gBuyOpenPrice;
       }
   }
   // Sell Trade
   else if(direction == -1)
   {
       gSellTicket = OpenMarketOrder(Symbol(), OP_SELL, gLotSize, "Initial Sell Order", clrRed);
       if(OrderSelect(gSellTicket, SELECT_BY_TICKET))
       {
          gSellOpenPrice = OrderOpenPrice(); 
          gBuyOpenPrice = NormalizeDouble((gSellOpenPrice + rz), _Digits);
          gSellTakeProfit = NormalizeDouble((gSellOpenPrice - tp), _Digits);
          gBuyTakeProfit = NormalizeDouble((gSellOpenPrice + (tp + rz)), _Digits);
          
          // ModifyStopsByPrice(gSellTicket, gBuyTakeProfit, gSellTakeProfit);       
          
          //open a recovery stop order in the opposite direction
          gLotSize = GetTradeVolume(2);
          gBuyStopTicket = OpenPendingOrder(Symbol(), OP_BUYSTOP, gLotSize, gBuyOpenPrice, 0, 0, "Initial Recovery Buy Stop)", 0, clrTurquoise);
          gCurrentDirection = direction;
          price = gSellOpenPrice;
       }
   }
   CreateProfitLine(direction, price, tp); 
}

void PlaceTrade(int pType)
{
    double tp = 0;
    double rz = 0;
    // if the user has selected to use the ATR to size zones
    if(UseATR == true)
    {
      double atr = iATR(_Symbol, PERIOD_D1, ATRPeriod, 1);
      tp = atr*ATRTPFraction;
      rz = atr*ATRZoneFraction;
      //TakeProfit = tp;
      //RecoveryZoneSize = rz;
    } else if(UseATR == false)
    {
      tp = TakeProfit*_Point;  // tp as price
      rz = RecoveryZoneSize*_Point; // rz  as price
    }
    if(CustomLotSize1 != 0) gLotSize = CustomLotSize1;
    else gLotSize = gInitialLotSize;
    
    if(pType == OP_BUYLIMIT)
    {
      gBuyStopTicket = OpenPendingOrder(_Symbol, OP_BUYLIMIT, gLotSize, PendingPrice, 0, 0, "Buy Limit Order", 0, 0);
      gBuyOpenPrice = PendingPrice;       
      gSellOpenPrice = NormalizeDouble((gBuyOpenPrice - rz), _Digits);
      gCurrentDirection = -1;
    
    } else if(pType == OP_BUYSTOP)
    {
      gBuyStopTicket = OpenPendingOrder(_Symbol, OP_BUYSTOP, gLotSize, PendingPrice, 0, 0, "Buy Stop Order", 0, 0);
      gBuyOpenPrice = PendingPrice;       
      gSellOpenPrice = NormalizeDouble((gBuyOpenPrice - rz), _Digits);
      gCurrentDirection = -1;
    
    } else if(pType == OP_SELLLIMIT)
    {
      gSellOpenPrice = PendingPrice; 
      gBuyOpenPrice = NormalizeDouble((gSellOpenPrice + rz), _Digits);
      gSellStopTicket = OpenPendingOrder(_Symbol, OP_SELLLIMIT, gLotSize, PendingPrice, 0, 0,  "Sell Limit Order", 0, 0);
      gCurrentDirection = 1;
    } else if(pType == OP_SELLSTOP)
    {
      gSellOpenPrice = PendingPrice; 
      gBuyOpenPrice = NormalizeDouble((gSellOpenPrice + rz), _Digits);
      gSellStopTicket = OpenPendingOrder(_Symbol, OP_SELLSTOP, gLotSize, PendingPrice, 0, 0,  "Sell Stop Order", 0, 0);
      gCurrentDirection = 1;
    }
    CreateProfitLine(gCurrentDirection, PendingPrice, 0);
}

// RSI Entry Function

int Is_RSI_OBOS_on_MTF(int shift)
{
   int direction = 0;
   
   // check if the MTF is showing oversold, buy signal
   double rsi = iRSI(_Symbol, PERIOD_M1, RSIPeriod, PRICE_CLOSE, shift);
   if((UseM1Timeframe == false) || (rsi < OversoldLevel))
   {
      rsi = iRSI(_Symbol, PERIOD_M5, RSIPeriod, PRICE_CLOSE, shift);
      if(UseM5Timeframe == false || (rsi < OversoldLevel))
      {
         rsi = iRSI(_Symbol, PERIOD_M15, RSIPeriod, PRICE_CLOSE, shift);
         if((UseM15Timeframe == false) || (rsi < OversoldLevel))
         {
            rsi = iRSI(_Symbol, PERIOD_M30, RSIPeriod, PRICE_CLOSE, shift);
            if((UseM30Timeframe == false) || (rsi < OversoldLevel))
            {
               rsi = iRSI(_Symbol, PERIOD_H1, RSIPeriod, PRICE_CLOSE, shift);
               if((UseH1Timeframe == false) || (rsi < OversoldLevel))
               {
                  rsi = iRSI(_Symbol, PERIOD_H4, RSIPeriod, PRICE_CLOSE, shift);
                  if((UseH4Timeframe == false) || (rsi < OversoldLevel))
                  {
                     rsi = iRSI(_Symbol, PERIOD_D1, RSIPeriod, PRICE_CLOSE, shift);
                     if((UseDailyTimeframe == false) || (rsi < OversoldLevel))
                     {
                        rsi = iRSI(_Symbol, PERIOD_W1, RSIPeriod, PRICE_CLOSE, shift);
                        if((UseWeeklyTimeframe == false) || (rsi < OversoldLevel))
                        {
                           rsi = iRSI(_Symbol, PERIOD_MN1, RSIPeriod, PRICE_CLOSE, shift);
                           if((UseMonthlyTimeframe == false) || (rsi < OversoldLevel))
                           {
                              direction = 1;
                              return direction;
                           }
                        }
                     }                     
                  }
               }
            }
         }
      }
   }
   
   // check if the MTF is showing overbought, sell signal   
   rsi = iRSI(_Symbol, PERIOD_M1, RSIPeriod, PRICE_CLOSE, shift);
   if((UseM1Timeframe == false) || (rsi > OverboughtLevel))
   {
      rsi = iRSI(_Symbol, PERIOD_M5, RSIPeriod, PRICE_CLOSE, shift);
      if(UseM5Timeframe == false || (rsi > OverboughtLevel))
      {
         rsi = iRSI(_Symbol, PERIOD_M15, RSIPeriod, PRICE_CLOSE, shift);
         if((UseM15Timeframe == false) || (rsi > OverboughtLevel))
         {
            rsi = iRSI(_Symbol, PERIOD_M30, RSIPeriod, PRICE_CLOSE, shift);
            if((UseM30Timeframe == false) || (rsi > OverboughtLevel))
            {
               rsi = iRSI(_Symbol, PERIOD_H1, RSIPeriod, PRICE_CLOSE, shift);
               if((UseH1Timeframe == false) || (rsi > OverboughtLevel))
               {
                  rsi = iRSI(_Symbol, PERIOD_H4, RSIPeriod, PRICE_CLOSE, shift);
                  if((UseH4Timeframe == false) || (rsi > OverboughtLevel))
                  {
                     rsi = iRSI(_Symbol, PERIOD_D1, RSIPeriod, PRICE_CLOSE, shift);
                     if((UseDailyTimeframe == false) || (rsi > OverboughtLevel))
                     {
                        rsi = iRSI(_Symbol, PERIOD_W1, RSIPeriod, PRICE_CLOSE, shift);
                        if((UseWeeklyTimeframe == false) || (rsi > OverboughtLevel))
                        {
                           rsi = iRSI(_Symbol, PERIOD_MN1, RSIPeriod, PRICE_CLOSE, shift);
                           if((UseMonthlyTimeframe == false) || (rsi > OverboughtLevel))
                           {
                              direction = -1;
                              return direction;
                           }
                        }
                     }                     
                  }
               }
            }
         }
      } 
   }
   return direction;      
}

void CloseOrdersAndReset()
{
   CloseAllMarketOrders();
   DeletePendingOrders(CLOSE_ALL_PENDING);
   gLotSize = gInitialLotSize;
   gCurrentDirection = 0;
   gBuyStopTicket = 0;
   gSellStopTicket = 0;
   gBuyTicket = 0;
   gSellTicket = 0;
   gRecoveryInitiated = false;
   DeleteProfitLine();
}

void CreateProfitLine(double pDirection, double pPrice, double pPoints)
{
   double price = 0;
   if(pDirection == 1)
   {
      price = NormalizeDouble(pPrice + pPoints, _Digits);
   } else if(pDirection == -1) {
      price = NormalizeDouble(pPrice - pPoints, _Digits);
   }
   ObjectCreate(0, PROFIT_LINE, OBJ_HLINE, 0,0,price);
   ObjectSetInteger(0, PROFIT_LINE, OBJPROP_COLOR, profitLineColor);
   ObjectSetInteger(0, PROFIT_LINE, OBJPROP_STYLE, STYLE_DASH);
}

void DeleteProfitLine()
{
   ObjectDelete(0, PROFIT_LINE);
}

void CreateTradingPanel()
{
   // create the button to start the trade off

   long buttonWidth = 50;
   long buttonHeight = 25;
   long panelX = Panel_X;
   long panelY = Panel_Y;
   long boxMargin = 10;
   long lableX = panelX+boxMargin+5;
   long lableY = panelY+boxMargin+10;
   long lableHeight = 40;
   long buttonX = panelX+boxMargin+20;
   long buttonY = panelY+lableHeight+boxMargin;
   long panelWidth = boxMargin+buttonWidth+boxMargin+buttonWidth+boxMargin +40;
   long panelHeight = boxMargin+lableHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin;
   double pending = NormalizeDouble(PendingPrice, _Digits);
   

   string buttonBox = "ButtonBox";   
   ObjectCreate(0, buttonBox, OBJ_RECTANGLE_LABEL, 0, 0, 0);
   ObjectSetInteger(0,buttonBox,OBJPROP_CORNER,CORNER_LEFT_UPPER);
   ObjectSetInteger(0, buttonBox, OBJPROP_XSIZE, panelWidth);
   ObjectSetInteger(0, buttonBox, OBJPROP_YSIZE, panelHeight);
   ObjectSetInteger(0, buttonBox, OBJPROP_XDISTANCE, panelX);
   ObjectSetInteger(0, buttonBox, OBJPROP_YDISTANCE, panelY);
   ObjectSetInteger(0, buttonBox, OBJPROP_BGCOLOR, Panel_Color);
   ObjectSetInteger(0,buttonBox,OBJPROP_BORDER_TYPE,BORDER_RAISED);
   ObjectSetInteger(0,buttonBox,OBJPROP_COLOR,clrGray);
   ObjectSetInteger(0,buttonBox,OBJPROP_SELECTABLE,false);
   ObjectSetInteger(0,buttonBox,OBJPROP_HIDDEN,false);
   ObjectSetInteger(0,buttonBox,OBJPROP_ZORDER,0);
   gTradingPanelObjects[0] = buttonBox;
   
   string panelLabel = "Trading Panel Label";
   ObjectCreate(0, panelLabel, OBJ_LABEL, 0,0,0);
   ObjectSetString(0, panelLabel, OBJPROP_TEXT, EA_NAME);
   ObjectSetInteger(0, panelLabel, OBJPROP_XDISTANCE, lableX);
   ObjectSetInteger(0, panelLabel, OBJPROP_YDISTANCE, lableY);
   ObjectSetInteger(0, panelLabel, OBJPROP_COLOR, Panel_Lable_Color);
   ObjectSetInteger(0, panelLabel, OBJPROP_FONTSIZE, 9);
   gTradingPanelObjects[1] = panelLabel;
   
   string sellButtonName = SELL_BUTTON;  
   ObjectCreate(0, sellButtonName, OBJ_BUTTON, 0, 0, 0);
   ObjectSetInteger(0, sellButtonName, OBJPROP_XSIZE, buttonWidth);
   ObjectSetInteger(0, sellButtonName, OBJPROP_YSIZE, buttonHeight);
   ObjectSetInteger(0, sellButtonName, OBJPROP_XDISTANCE, buttonX);
   ObjectSetInteger(0, sellButtonName, OBJPROP_YDISTANCE, buttonY);
   ObjectSetInteger(0, sellButtonName, OBJPROP_COLOR, Panel_Lable_Color);
   ObjectSetInteger(0, sellButtonName, OBJPROP_BGCOLOR, clrRed);
   ObjectSetString(0, sellButtonName, OBJPROP_TEXT, "Sell");
   gTradingPanelObjects[2] = SELL_BUTTON;
     
   string buyButtonName = BUY_BUTTON;
   ObjectCreate(0, buyButtonName, OBJ_BUTTON, 0, 0, 0);
   ObjectSetInteger(0, buyButtonName, OBJPROP_XSIZE, buttonWidth);
   ObjectSetInteger(0, buyButtonName, OBJPROP_YSIZE, buttonHeight);
   ObjectSetInteger(0, buyButtonName, OBJPROP_XDISTANCE, (buttonX+buttonWidth+boxMargin));
   ObjectSetInteger(0, buyButtonName, OBJPROP_YDISTANCE, buttonY);
   ObjectSetInteger(0, buyButtonName, OBJPROP_COLOR, Panel_Lable_Color);
   ObjectSetInteger(0, buyButtonName, OBJPROP_BGCOLOR, clrGreen);
   ObjectSetString(0, buyButtonName, OBJPROP_TEXT, "Buy");
   gTradingPanelObjects[3] = BUY_BUTTON; 
   
   ObjectCreate(0, CLOSE_ALL_BUTTON, OBJ_BUTTON, 0, 0, 0);
   ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_XSIZE, buttonWidth+boxMargin+buttonWidth);
   ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_YSIZE, buttonHeight);
   ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_XDISTANCE, (buttonX));
   ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_YDISTANCE, buttonY+buttonHeight+boxMargin);
   ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_COLOR, Panel_Lable_Color);
   ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_BGCOLOR, clrGray);
   ObjectSetString(0, CLOSE_ALL_BUTTON, OBJPROP_TEXT, "Close All Orders");
   gTradingPanelObjects[4] = CLOSE_ALL_BUTTON;
   
   string TPLabel = "TP Label";
   ObjectCreate(0, TPLabel, OBJ_LABEL, 0, 0, 0);
   ObjectSetString(0, TPLabel, OBJPROP_TEXT, "TP: ");
   ObjectSetInteger(0, TPLabel, OBJPROP_XDISTANCE, buttonX);
   ObjectSetInteger(0, TPLabel, OBJPROP_YDISTANCE, 5+buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin);
   ObjectSetInteger(0, TPLabel, OBJPROP_COLOR, Panel_Lable_Color);
   gTradingPanelObjects[5] = TPLabel;
   
   string zoneLable = "Zone Lable";
   ObjectCreate(0, zoneLable, OBJ_LABEL, 0, 0, 0);
   ObjectSetString(0, zoneLable, OBJPROP_TEXT, "Zone: ");
   ObjectSetInteger(0, zoneLable, OBJPROP_XDISTANCE, buttonX);
   ObjectSetInteger(0, zoneLable, OBJPROP_YDISTANCE, 5+ buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin);
   ObjectSetInteger(0, zoneLable, OBJPROP_COLOR, Panel_Lable_Color);
   gTradingPanelObjects[6] = zoneLable;
   
   ObjectCreate(0, TP_EDIT, OBJ_EDIT, 0, 0, 0);
   ObjectSetInteger(0, TP_EDIT, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   ObjectSetInteger(0, TP_EDIT, OBJPROP_XDISTANCE, buttonX+buttonWidth+boxMargin);
   ObjectSetInteger(0, TP_EDIT, OBJPROP_YDISTANCE, buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin);
   ObjectSetInteger(0, TP_EDIT, OBJPROP_XSIZE, buttonWidth);
   ObjectSetInteger(0, TP_EDIT, OBJPROP_YSIZE, buttonHeight);   
   ObjectSetInteger(0, TP_EDIT, OBJPROP_COLOR, clrBlack);
   ObjectSetInteger(0, TP_EDIT, OBJPROP_BGCOLOR, clrWhite);
   ObjectSetString(0, TP_EDIT, OBJPROP_TEXT, IntegerToString(TakeProfit));
   ObjectSetInteger(0,TP_EDIT,OBJPROP_ALIGN,ALIGN_CENTER);
   gTradingPanelObjects[7] = TP_EDIT;
   
   ObjectCreate(0, ZONE_EDIT, OBJ_EDIT, 0, 0, 0);
   ObjectSetInteger(0, ZONE_EDIT, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   ObjectSetInteger(0, ZONE_EDIT, OBJPROP_XDISTANCE, buttonX+buttonWidth+boxMargin);
   ObjectSetInteger(0, ZONE_EDIT, OBJPROP_YDISTANCE, buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin);   
   ObjectSetInteger(0, ZONE_EDIT, OBJPROP_XSIZE, buttonWidth);
   ObjectSetInteger(0, ZONE_EDIT, OBJPROP_YSIZE, buttonHeight);
   ObjectSetInteger(0, ZONE_EDIT, OBJPROP_COLOR, clrBlack);
   ObjectSetInteger(0, ZONE_EDIT, OBJPROP_BGCOLOR, clrWhite);
   ObjectSetString(0, ZONE_EDIT, OBJPROP_TEXT, IntegerToString(RecoveryZoneSize));
   ObjectSetInteger(0,ZONE_EDIT,OBJPROP_ALIGN,ALIGN_CENTER);
   gTradingPanelObjects[8] = ZONE_EDIT;
   
   ObjectCreate(0, PENDING_EDIT, OBJ_EDIT, 0, 0, 0);
   ObjectSetInteger(0, PENDING_EDIT, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   ObjectSetInteger(0, PENDING_EDIT, OBJPROP_XDISTANCE, buttonX+buttonWidth+boxMargin);
   ObjectSetInteger(0, PENDING_EDIT, OBJPROP_YDISTANCE, buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin);   
   ObjectSetInteger(0, PENDING_EDIT, OBJPROP_XSIZE, buttonWidth);
   ObjectSetInteger(0, PENDING_EDIT, OBJPROP_YSIZE, buttonHeight);
   ObjectSetInteger(0, PENDING_EDIT, OBJPROP_COLOR, clrBlack);
   ObjectSetInteger(0, PENDING_EDIT, OBJPROP_BGCOLOR, clrWhite);
   ObjectSetString(0, PENDING_EDIT, OBJPROP_TEXT, IntegerToString(pending));
   ObjectSetInteger(0,PENDING_EDIT,OBJPROP_ALIGN,ALIGN_CENTER);
   gTradingPanelObjects[9] = PENDING_EDIT;
      
   string pendingLabel = "Pending Label";
   ObjectCreate(0, pendingLabel, OBJ_LABEL, 0, 0, 0);
   ObjectSetString(0, pendingLabel, OBJPROP_TEXT, "Price: ");
   ObjectSetInteger(0, pendingLabel, OBJPROP_XDISTANCE, buttonX);
   ObjectSetInteger(0, pendingLabel, OBJPROP_YDISTANCE, 5+ buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin);
   ObjectSetInteger(0, pendingLabel, OBJPROP_COLOR, Panel_Lable_Color);
   gTradingPanelObjects[10] = pendingLabel;  
   
}

// Panel action buttons
void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
{
   if(sparam == SELL_BUTTON && gCurrentDirection == 0)
   {
      if(gCurrentDirection == 0 && PendingPrice == 0) TakeTrade((int)-1);
      else if(PendingPrice > Bid) PlaceTrade(OP_SELLLIMIT);
      else if(PendingPrice < Bid) PlaceTrade(OP_SELLSTOP);
   }
   else if(sparam == BUY_BUTTON && gCurrentDirection == 0)
   {
      if(gCurrentDirection == 0 && PendingPrice == 0) TakeTrade((int)1);
      else if(PendingPrice > Ask) PlaceTrade(OP_BUYSTOP);
      else if(PendingPrice < Ask) PlaceTrade(OP_BUYLIMIT);
   }
   else if(sparam == CLOSE_ALL_BUTTON)
   {
      CloseOrdersAndReset();
      Print("Close all pressed.");
   }
   
   else if(id == CHARTEVENT_OBJECT_ENDEDIT && sparam == TP_EDIT)
   {
      string takeProfitString = ObjectGetString(0, TP_EDIT, OBJPROP_TEXT);
      TakeProfit = StringToPips(takeProfitString);
   }
   else if(id == CHARTEVENT_OBJECT_ENDEDIT && sparam == ZONE_EDIT)
   {
      string zoneString = ObjectGetString(0, ZONE_EDIT, OBJPROP_TEXT);
      RecoveryZoneSize = StringToPips(zoneString);
   }
   else if(id == CHARTEVENT_OBJECT_ENDEDIT && sparam == PENDING_EDIT)
   {
      string pendingString = ObjectGetString(0, PENDING_EDIT, OBJPROP_TEXT);
      PendingPrice = NormalizeDouble(StringToDouble(pendingString), _Digits);
   }
   
}


void DeleteTradePanel()
{
   for(int count = 0; count <= ArraySize(gTradingPanelObjects)-1; count++)
   {
      if(ArraySize(gTradingPanelObjects) > 0)
      {
         string objectName = gTradingPanelObjects[count];
         ObjectDelete(0, objectName);
      }
   }
}

// USEFUL FUNCTIONS

// Pip Point Function
double PipPoint(string Currency)
   {
      double CalcPoint = 0; 
      double CalcDigits = MarketInfo(Currency,MODE_DIGITS);
      if(CalcDigits == 2 || CalcDigits == 3) CalcPoint = 0.01;
      else if(CalcDigits == 4 || CalcDigits == 5) CalcPoint = 0.0001;
      else if(CalcDigits == 0) CalcPoint = 0;
      else if(CalcDigits == 1) CalcPoint = 0.1;
      return(CalcPoint);
   }
   
double GetSlippage(string Currency, int SlippagePips) 
   { 
      double CalcSlippage = SlippagePips;
      int CalcDigits = (int)MarketInfo(Currency,MODE_DIGITS); 
      if(CalcDigits == 0 || CalcDigits == 1 || CalcDigits == 2 || CalcDigits == 4) CalcSlippage = SlippagePips; 
      else if(CalcDigits == 3 || CalcDigits == 5) CalcSlippage = SlippagePips; 
      return(CalcSlippage); 
   }
   
int GetPoints(int Pips)
   {
      int CalcPoint = Pips; 
      double CalcDigits = MarketInfo(Symbol(),MODE_DIGITS);
      if(CalcDigits == 0 || CalcDigits == 1 || CalcDigits == 2 || CalcDigits == 4) CalcPoint = Pips;
      return(CalcPoint);
   }
   
int StringToPips(string text)
{
   int pips = StringToInteger(text);
   if(pips <= 0)
   {
      Alert("Invalid pips from string: ", pips);
   }
   return pips;
}



void CloseAllMarketOrders()
{
   int retryCount = 0;
   
   for(int Counter = 0; Counter <= OrdersTotal()-1; Counter++)
   {
      if(OrderSelect(Counter,SELECT_BY_POS))
      {
         if(OrderMagicNumber() == MagicNumber && OrderSymbol() == _Symbol && (OrderType() == OP_BUY || OrderType() == OP_SELL))
         {
            // Close Order
            int CloseTicket = OrderTicket();
            double CloseLots = OrderLots();
            while(IsTradeContextBusy()) Sleep(10);
            
            RefreshRates();            
            double ClosePrice = MarketInfo(_Symbol,MODE_BID);
            if(OrderType() == OP_SELL) ClosePrice = MarketInfo(_Symbol, MODE_ASK);

            bool Closed = OrderClose(CloseTicket,CloseLots,ClosePrice,Slippage,Red);
            // Error Handling
            if(Closed == false)
            {
               int ErrorCode = GetLastError();
               string ErrAlert = StringConcatenate("Close All Market Orders - Error ",ErrorCode,".");
               Alert(ErrAlert);
               Print(ErrAlert);
            } else Counter--;
         }
      }  
    }
}

double GetTradeVolume(int pTradeNo)
{
   double lots = 0;
   double volume = 0;
   if(CustomLotSize1 == 0)
   {
      lots = (gLotSize*LotMultiplier)+LotAdditions; //increase the lot size
   } else if(CustomLotSize1 != 0){
      if(pTradeNo > 10) {
         Alert("No of trades exceeds custom lot size inputs (10)");
         return -1;
      } else {
         lots = gCustomLotSizes[pTradeNo-1];
      }
   }
   volume = CheckVolume(_Symbol, lots);
   return volume;
}

// Verify and adjust trade volume
double CheckVolume(string pSymbol,double pVolume)
{
	double minVolume = SymbolInfoDouble(pSymbol,SYMBOL_VOLUME_MIN);
	double maxVolume = SymbolInfoDouble(pSymbol,SYMBOL_VOLUME_MAX);
	double stepVolume = SymbolInfoDouble(pSymbol,SYMBOL_VOLUME_STEP);
	
	double tradeSize;
	if(pVolume < minVolume) 
	{
	   Alert("Sent volume is smaller than the minimum volume for this symbol: ", _Symbol, ", min: ", minVolume, ", sent: ", pVolume);
	   tradeSize = minVolume;
	}
	else if(pVolume > maxVolume)
	{
	   Alert("Sent volume is larger than the maximum volume for this symbol: ", _Symbol, ", max: ", maxVolume, ", sent: ", pVolume);	   
	   tradeSize = maxVolume;
	}   
	else tradeSize = MathRound(pVolume / stepVolume) * stepVolume;
	
	if(stepVolume >= 0.1) tradeSize = NormalizeDouble(tradeSize,1);
	else tradeSize = NormalizeDouble(tradeSize,2);
	
	return(tradeSize);
}

bool DeletePendingOrders(CLOSE_PENDING_TYPE pDeleteType)
{
   bool error = false;
   bool deleteOrder = false;
   
   // Loop through open order pool from oldest to newest
   for(int order = 0; order <= OrdersTotal() - 1; order++)
   {
      // Select order
      bool result = OrderSelect(order,SELECT_BY_POS);
      
      int orderType = OrderType();
      int orderMagicNumber = OrderMagicNumber();
      int orderTicket = OrderTicket();
      double orderVolume = OrderLots();
      
      // Determine if order type matches pCloseType
      if( (pDeleteType == CLOSE_ALL_PENDING && orderType != OP_BUY && orderType != OP_SELL)
         || (pDeleteType == CLOSE_BUY_LIMIT && orderType == OP_BUYLIMIT) 
         || (pDeleteType == CLOSE_SELL_LIMIT && orderType == OP_SELLLIMIT) 
         || (pDeleteType == CLOSE_BUY_STOP && orderType == OP_BUYSTOP)
         || (pDeleteType == CLOSE_SELL_STOP && orderType == OP_SELLSTOP) )
      {
         deleteOrder = true;
      }
      else deleteOrder = false;
      
      // Close order if pCloseType and magic number match currently selected order
      if(deleteOrder == true && orderMagicNumber == MagicNumber && OrderSymbol() == Symbol())
      {
         result = OrderDelete(orderTicket);
         
         if(result == false)
         {
            Print("Delete multiple orders, failed to delete order: ", orderTicket);
            error = true;
         }
         else order--;
      }
   }
   
   return(error);
}

int OpenPendingOrder(string pSymbol,int pType,double pVolume,double pPrice,double pStop,double pProfit,string pComment,datetime pExpiration,color pArrow)
{
   int retryCount = 0;
	int ticket = 0;
	int errorCode = 0;
	int max_attempts = 5;

	string orderType;
	string errDesc;
	
	// Order retry loop
	while(retryCount <= max_attempts)
	{
		while(IsTradeContextBusy()) Sleep(10);
		ticket = OrderSend(pSymbol, pType, pVolume, pPrice, Slippage, pStop, pProfit, pComment, MagicNumber, pExpiration, pArrow);
		
		// Error handling
   	if(ticket == -1)
   	{
   		errorCode = GetLastError();
   		bool checkError = RetryOnError(errorCode);
      	
      	// Unrecoverable error
      	if(checkError == false)  
   		{
     			Alert("Open ",orderType," order: Error ",errorCode,".");
     			Print("Symbol: ",pSymbol,", Volume: ",pVolume,", Price: ",pPrice,", SL: ",pStop,", TP: ",pProfit,", Expiration: ",pExpiration);
   			break;
   		}
   		
   		// Retry on error
   		else
   		{
   			Print("Server error detected, retrying...");
   			Sleep(3000);
   			retryCount++;
   		}
   	}
   	
   	// Order successful
   	else
   	{
   	   Comment(orderType," order #",ticket," opened on ",_Symbol);
   	   Print(orderType," order #",ticket," opened on ",_Symbol);
   	   break;
   	} 
   }
   
   // Failed after retry
	if(retryCount > max_attempts)
	{
		Alert("Open ",orderType," order: Max retries exceeded. Error ",errorCode," - ",errDesc);
		Print("Symbol: ",pSymbol,", Volume: ",pVolume,", Price: ",pPrice,", SL: ",pStop,", TP: ",pProfit,", Expiration: ",pExpiration);
	}

	return(ticket);
}

bool RetryOnError(int pErrorCode)
{
	// Retry on these error codes
	switch(pErrorCode)
	{
		case ERR_BROKER_BUSY:
		case ERR_COMMON_ERROR:
		case ERR_NO_ERROR:
		case ERR_NO_CONNECTION:
		case ERR_NO_RESULT:
		case ERR_SERVER_BUSY:
		case ERR_NOT_ENOUGH_RIGHTS:
      case ERR_MALFUNCTIONAL_TRADE:
      case ERR_TRADE_CONTEXT_BUSY:
      case ERR_TRADE_TIMEOUT:
      case ERR_REQUOTE:
      case ERR_TOO_MANY_REQUESTS:
      case ERR_OFF_QUOTES:
      case ERR_PRICE_CHANGED:
      case ERR_TOO_FREQUENT_REQUESTS:
		
		return(true);
	}
	
	return(false);
}

int OpenMarketOrder(string pSymbol, int pType, double pVolume, string pComment, color pArrow)
{
	int retryCount = 0;
	int ticket = 0;
	int errorCode = 0;
	int max_attempts = 5;
	int wait_time = 3000;
	
	double orderPrice = 0;
	
	string orderType;
	string errDesc;
	
	// Order retry loop
	while(retryCount <= max_attempts) 
	{
		while(IsTradeContextBusy()) Sleep(10);
		
		// Get current bid/ask price
		if(pType == OP_BUY) orderPrice = MarketInfo(pSymbol,MODE_ASK);
		else if(pType == OP_SELL) orderPrice = MarketInfo(pSymbol,MODE_BID);

		// Place market order
		ticket = OrderSend(pSymbol,pType,pVolume,orderPrice,Slippage,0,0,pComment,MagicNumber,0,pArrow);
	   
		// Error handling
		if(ticket == -1)
		{
			errorCode = GetLastError();
			bool checkError = RetryOnError(errorCode);
			
			// Unrecoverable error
			if(checkError == false)
			{
				Alert("Open ",orderType," order: Error ",errorCode,".");
				Print("Symbol: ",pSymbol,", Volume: ",pVolume,", Price: ",orderPrice);
				break;
			}
			
			// Retry on error
			else
			{
				Print("Server error detected, retrying...");
				Sleep(wait_time);
				retryCount++;
			}
		}
		
		// Order successful
		else
		{
		   Comment(orderType," order #",ticket," opened on ",pSymbol);
		   Print(orderType," order #",ticket," opened on ",pSymbol);
		   break;
		} 
   }
   
   // Failed after retry
	if(retryCount > max_attempts)
	{
		Alert("Open ",orderType," order: Max retries exceeded. Error ",errorCode," - ",errDesc);
		Print("Symbol: ",pSymbol,", Volume: ",pVolume,", Price: ",orderPrice);
	}
   
   return(ticket);
} 

// Return trade size based on risk per trade of stop loss in points
double GetTradeSize(string pSymbol, double pFixedVol, double pPercent, int pStopPoints)
{
	double tradeSize;
	
	if(pPercent > 0 && pStopPoints > 0)
	{
		if(pPercent > 10) pPercent = 10;
		
		double margin = AccountInfoDouble(ACCOUNT_BALANCE) * (pPercent / 100);
		double tickSize = SymbolInfoDouble(pSymbol,SYMBOL_TRADE_TICK_VALUE);
		
		tradeSize = (margin / pStopPoints) / tickSize;
		tradeSize = CheckVolume(pSymbol,tradeSize);
		
		return(tradeSize);
	}
	else
	{
		tradeSize = pFixedVol;
		tradeSize = CheckVolume(pSymbol,tradeSize);
		
		return(tradeSize);
	}
}

// Create datetime value
datetime CreateDateTime(int pHour = 0, int pMinute = 0) 
{
	MqlDateTime timeStruct;
	TimeToStruct(TimeCurrent(),timeStruct);
	
	timeStruct.hour = pHour;
	timeStruct.min = pMinute;
	
	datetime useTime = StructToTime(timeStruct);
	
	return(useTime);
}

// Check timer
bool CheckDailyTimer()
{
   datetime TimeStart = CreateDateTime(StartHour, StartMinute);
   datetime TimeEnd = CreateDateTime(EndHour, EndMinute);
   
   datetime currentTime;
	if(UseLocalTime == true) currentTime = TimeLocal();
	else currentTime = TimeCurrent();
   
   // check if the timer goes over midnight
	if(TimeEnd <= TimeStart)	
	{
		TimeStart -= 86400;
		
		if(currentTime > TimeEnd)
		{
			TimeStart += 86400;
			TimeEnd += 86400;
		}
	} 
	
	bool timerOn = false;
	if(currentTime >= TimeStart && currentTime < TimeEnd) 
	{
		timerOn = true;
	}
	
	return(timerOn);
}


void FindOpenOrders()
{
   double largest_lots = 0;
   int ticket = -1;
   int open_orders = 0;
   int stopTicket = 0;
   for(int Counter = 0; Counter <= OrdersTotal()-1; Counter++)
   {
      if(OrderSelect(Counter,SELECT_BY_POS))
      {
         if(OrderMagicNumber() == MagicNumber && OrderSymbol() == _Symbol && (OrderType() == OP_BUY || OrderType() == OP_SELL))
         {
            open_orders++;
            if(OrderLots() > largest_lots)
            { 
               ticket = OrderTicket();
               largest_lots = OrderLots();
            }
         }
         if(OrderMagicNumber() == MagicNumber && OrderSymbol() == _Symbol && OrderType() == OP_BUYSTOP)
         {
            gBuyStopTicket = OrderTicket();
            stopTicket = gBuyStopTicket;
         } else if(OrderMagicNumber() == MagicNumber && OrderSymbol() == _Symbol && OrderType() == OP_SELLSTOP)
         {
            gSellStopTicket = OrderTicket();
            stopTicket = gSellStopTicket;
         }
      }
   }
   
   if(ticket > 0)
   {
      if(OrderSelect(ticket, SELECT_BY_TICKET))
      {
         int type = OrderType();
         if(type == OP_BUY)
         {
            gCurrentDirection = 1;
            gBuyTicket = ticket;
         } else if(type == OP_SELL)
         {
            gCurrentDirection = -1;
            gSellTicket = ticket;
         }   
         if(open_orders > 1) gRecoveryInitiated = true;
      }
      Print("Check for orders complete, resuming recovery direction of trade: ", ticket, " with recovery stop: ", stopTicket, " in place. ", open_orders, " orders already opened.");
   } else {
      Print("Check for orders complete, none currently open.");
   }     
}         

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---