Untitled

mail@pastecode.io avatar
unknown
c_cpp
2 years ago
66 kB
0
Indexable
Never
//+------------------------------------------------------------------+
//|                                                  pmhouse_ZR_v7p4 |
//|                                                       A. Sweeney |
//+------------------------------------------------------------------+

#property copyright     "Click here for the latest version"
#property description   "Coded by: A Sweeney - Updated: pcei"
#property link "https://oneglancetrader.com/download"
#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 UtilitySettings; // ** UTILITY SETTINGS **
input bool Push_Notifications = true;
input bool WriteSpreadHistory = false;
input string SpreadFileName_csv = "spreadHistory.csv";

sinput string RecoverySettings; // ** ZONE RECOVERY SETTINGS **
input int HeSoPoint = 100000; //GU:100000; BTC:100; JPY-XAU:1000
input int SlippageOpenOrder = 3;
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 = 30; // Recovery Take Profit (points).
extern double PendingPrice = 0; // Price for pending orders

//sinput string ATRHeader; // ** ATR Dynamic Zone Sizing **
bool UseATR = false; // Use ATR?
int ATRPeriod = 14; // ATR Period
double ATRZoneFraction = 0.2; // Fraction of ATR to use as Recovery Zone
double ATRTPFraction = 0.3; // Fraction or ATR to use for TP sizes
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.01; // 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 **
 bool UseTimer = false; // Use a Trade Timer?
 int StartHour = 0; // Start Hour
 int StartMinute = 0; // Start Minute
 int EndHour = 0; // End Hour
 int EndMinute = 0; // End Minute
 bool UseLocalTime = false; // Use local time?

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

sinput string Visuals; // ** VISUALS **
input color profitLineColor = clrLightSeaGreen;
input int Panel_X = 120; // 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 = 030589; // Magic Number
input int Slippage = 100; // Slippage Max (Points).
 bool TradeOnBarOpen = true; // Trade on New Bar?
 int speed = 500; // Back tester speed
 double TestCommission = 7; // Back tester simulated commission


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

#define EA_NAME "pmhouse_ZR_v7p4"
#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()
  {



//Write spread history to a specific file:
   if(WriteSpreadHistory == true)
     {
      int countAlert = 0;
      if(countAlert < 1)
        {
         Alert("Writing the spread to file...");
         countAlert++;
        }
      saveSpread(SpreadFileName_csv);
     }
   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 = (int)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 + minRecoveryZone())*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 + minRecoveryZone();
      if(UseRecoveryTakeProfit == false || gRecoveryInitiated == false)
        {
         profitTarget = (TakeProfit + minRecoveryZone())*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), ", MinRZS: ", IntegerToString(minRecoveryZone())));
        }

      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
      double temp_profitPrice = 0;
      if(gCurrentDirection == 1 && netLotSize != 0)
        {
         tp = (profitTarget + tradeCosts - currentProfit)*_Point/(point_value*netLotSize);
         double   profitPrice = NormalizeDouble(Bid + tp, _Digits);
         temp_profitPrice = profitPrice;
         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);
            temp_profitPrice = profitPrice;
            if(!ObjectSetDouble(0, PROFIT_LINE, OBJPROP_PRICE, profitPrice))
               Print("Could not set line");
           }

         SymbolProfitAtSpecificPrice(temp_profitPrice);
         

      // 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
           {
            static int counterAlert1 = 0;
            if(counterAlert1 < 1)
              {
               string message = "Warning - EA could not find the recovery Sell Stop for " + Symbol();
               sendNotification(AccountName() + " - " + Symbol() + " cannot open the SELL STOP order");
               Alert(message);
               Print(message);
               counterAlert1++;
              }
           }
        }
      // 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
           {
            static int counterAlert2 = 0 ;
            if(counterAlert2 < 1)
              {
               string message = "Warning - EA could not find the recovery Buy Stop" + Symbol();
               sendNotification(AccountName() + " - " + Symbol() + " cannot open the BUY STOP order");
               Alert(message);
               Print(message);
               counterAlert2++;
              }
           }
        }
     }
   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)
        {
         if(RecoveryZoneSize < minRecoveryZone())
           {
            rz = 5*(RecoveryZoneSize + minRecoveryZone())*_Point;
           }
         else
           {
            rz = RecoveryZoneSize*_Point;
           }

         if(TakeProfit < minRecoveryZone())
           {
            tp = 5*(TakeProfit + minRecoveryZone())*_Point;
           }
         else
           {
            tp = TakeProfit*_Point;
           }
        }
   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)
        {
         if(RecoveryZoneSize < minRecoveryZone())
           {
            rz = 5*(RecoveryZoneSize + minRecoveryZone())*_Point;
           }
         else
           {
            rz = RecoveryZoneSize*_Point;
           }

         if(TakeProfit < minRecoveryZone())
           {
            tp = 5*(TakeProfit + minRecoveryZone())*_Point;
           }
         else
           {
            tp = TakeProfit*_Point;
           }

        }
   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, MarketInfo(Symbol(), MODE_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 = (int) StringToInteger(text);
   if(pips <= 0)
     {
      Alert("Invalid pips from string: ", pips);
      sendNotification(AccountName() + " - " + Symbol() + " Invalid pips from string: " + IntegerToString(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);
               sendNotification(AccountName() + " - " + Symbol() + " - " + 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)");
            sendNotification(AccountName() + " - " + Symbol() + " - " + "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: ", DoubleToString(minVolume), ", sent: ", DoubleToString(pVolume));
      sendNotification(AccountName() + " - " + Symbol() + " - " + "Sent volume is smaller than the minimum volume: " + DoubleToString(minVolume) + " sent: " + DoubleToString(pVolume));
      tradeSize = minVolume;
     }
   else
      if(pVolume > maxVolume)
        {
         Alert("Sent volume is larger than the maximum volume for this symbol: ", _Symbol, ", max: ", DoubleToString(maxVolume), ", sent: ", DoubleToString(pVolume));
         sendNotification(AccountName() + " - " + Symbol() + " - " + "Sent volume is larger than the maximum volume: " + DoubleToString(maxVolume) + " sent: " + DoubleToString(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)
        {
         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);

      while(true)
        {
         if(pType == OP_SELLSTOP)
           {
            if((MarketInfo(Symbol(),MODE_BID) > pPrice) && ((MarketInfo(Symbol(),MODE_BID) - pPrice)*HeSoPoint > (MarketInfo(Symbol(), MODE_STOPLEVEL)+SlippageOpenOrder)))
              {
               ticket = OrderSend(pSymbol, pType, pVolume, pPrice, Slippage, pStop, pProfit, pComment, MagicNumber, pExpiration, pArrow);
               break;
              }
           }
         else
            if(pType == OP_BUYSTOP)
              {
               if((MarketInfo(Symbol(),MODE_ASK) < pPrice) && ((pPrice - MarketInfo(Symbol(),MODE_ASK))*HeSoPoint > (MarketInfo(Symbol(), MODE_STOPLEVEL)+SlippageOpenOrder)))
                 {
                  ticket = OrderSend(pSymbol, pType, pVolume, pPrice, Slippage, pStop, pProfit, pComment, MagicNumber, pExpiration, pArrow);
                  break;
                 }
              }
            else
               if(pType == OP_BUYLIMIT)
                 {
                  ticket = OrderSend(pSymbol, pType, pVolume, pPrice, Slippage, pStop, pProfit, pComment, MagicNumber, pExpiration, pArrow);
                  break;
                 }
               else
                  if(pType == OP_SELLLIMIT)
                    {
                     ticket = OrderSend(pSymbol, pType, pVolume, pPrice, Slippage, pStop, pProfit, pComment, MagicNumber, pExpiration, pArrow);
                     break;
                    }
        }

      // Error handling
      if(ticket == -1)
        {
         errorCode = GetLastError();
         bool checkError = RetryOnError(errorCode);

         // Unrecoverable error
         if(checkError == false)
           {
            Alert("Open ",orderType," order: Error ",errorCode,".");
            sendNotification(AccountName() + " - " + Symbol() + " - " + "Open " + orderType + " order: Error " + IntegerToString(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);
      sendNotification(AccountName() + " - " + Symbol() + " - " + "Open " + orderType + " order: Max retries exceeded. Error " + IntegerToString(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,".");
            sendNotification(AccountName() + " - " + Symbol() + " - " + "Open " + orderType + " order: Error " + IntegerToString(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);
      sendNotification(AccountName() + " - " + Symbol() + " - " + "Open " + orderType + " order: Max retries exceeded. Error " + IntegerToString(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.");
     }
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int minRecoveryZone()
  {

   int minRZS_point = 0;
   minRZS_point = (int)(MarketInfo(Symbol(), MODE_SPREAD) + MarketInfo(Symbol(), MODE_STOPLEVEL));

   return minRZS_point;
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void saveSpread(string filename)
  {
   static double firstSpread = MarketInfo(Symbol(),MODE_SPREAD);
   if(MarketInfo(Symbol(),MODE_SPREAD) != firstSpread)
     {
      int filehandle=FileOpen(filename,FILE_READ|FILE_WRITE|FILE_CSV|FILE_ANSI);

      FileSeek(filehandle, 0, SEEK_END);

      FileWrite(filehandle,TimeCurrent(),Symbol(), EnumToString(ENUM_TIMEFRAMES(_Period)), MarketInfo(Symbol(), MODE_SPREAD));

      FileClose(filehandle);

      firstSpread = MarketInfo(Symbol(),MODE_SPREAD);
     }
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void sendNotification(string notiMess)
  {

   if(Push_Notifications)
      SendNotification(notiMess);

  }


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void PrintText(string object, string text, int x, int y, color colorText)
  {
   ObjectCreate(object, OBJ_LABEL, 0, 0, 0);
   ObjectSetText(object, text, 9, "Verdana", colorText);
   ObjectSet(object, OBJPROP_CORNER, CORNER_RIGHT_LOWER);
   ObjectSet(object, OBJPROP_XDISTANCE, x);
   ObjectSet(object, OBJPROP_YDISTANCE, y);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void SymbolProfitAtSpecificPrice(double SpecificPrice)
  {
   //Alert(SpecificPrice);
   double point_value = Point()*MarketInfo(Symbol(), MODE_TICKVALUE)/MarketInfo(Symbol(), MODE_TICKSIZE);

   double currentProfit = 0;
   double totalCommision = 0;
   double totalSpreadCosts = 0;
   double tradeCosts = 0;
   double profitTarget = 0;

   double stoplossTarget = 0;
    double totalprofit = 0 ;

   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      double temp_profitTarget_buy = 0 ;
      double temp_stoplossTarget_sell = 0 ;
      double temp_profitTarget_sell = 0 ;
      double temp_stoplossTarget_buy = 0;

      if(OrderSelect(i,SELECT_BY_POS))
        {
         if(OrderSymbol() == Symbol())
           {
            if(OrderType() == OP_BUY && SpecificPrice > OrderOpenPrice())
              {
               double  tp_target = MathAbs(SpecificPrice - OrderOpenPrice())/Point;
               temp_profitTarget_buy = NormalizeDouble(tp_target*point_value*OrderLots(),2);
              }

            if(OrderType() == OP_SELL && SpecificPrice < OrderOpenPrice())
              {
               double  tp_target = MathAbs(SpecificPrice - OrderOpenPrice())/Point;
               temp_profitTarget_sell = NormalizeDouble(tp_target*point_value*OrderLots(),2);
              }

            if(OrderType() == OP_BUY && SpecificPrice <= OrderOpenPrice())
              {
               double sl_target = MathAbs(OrderOpenPrice() - SpecificPrice)/Point;
               temp_stoplossTarget_buy = NormalizeDouble(sl_target*point_value*OrderLots(),2);
              }

            if(OrderType() == OP_SELL && SpecificPrice >= OrderOpenPrice())
              {
               double sl_target = MathAbs(SpecificPrice - OrderOpenPrice())/Point;
               temp_stoplossTarget_sell = NormalizeDouble(sl_target*point_value*OrderLots(),2);
              }

            currentProfit += OrderProfit();
            totalSpreadCosts += (OrderLots()*MarketInfo(Symbol(), MODE_SPREAD)*point_value);
            totalCommision += OrderCommission();
           }
           profitTarget += (temp_profitTarget_buy + temp_profitTarget_sell);
           stoplossTarget += (temp_stoplossTarget_buy + temp_stoplossTarget_sell);
        }
     
     }

   tradeCosts = totalCommision; //+totalSpreadCosts
   currentProfit = currentProfit + tradeCosts;
   totalprofit = profitTarget - stoplossTarget + tradeCosts;


 //PrintText("profitTarget", "Profit at " + NormalizeDouble(SpecificPrice, MarketInfo(Symbol(), MODE_DIGITS)) + " : " + DoubleToString(profitTarget,2) + "$", 20, 100, Blue);
 //PrintText("stoplossTarget", "Stoploss at " + NormalizeDouble(SpecificPrice, MarketInfo(Symbol(), MODE_DIGITS)) + " : " + DoubleToString(stoplossTarget,2) + "$", 20, 120, Red);
 PrintText("currentProfit", "Current Profit: " + DoubleToString(currentProfit,2) + "$", 20, 40, Blue);
 PrintText("totalprofit", "Total profit at profit line: " + DoubleToString(totalprofit,2) + "$", 20, 20, Green);

  // return totalprofit;
  }
//+------------------------------------------------------------------+