← К каталогу
Исходный код · ID 1161

OGT Zone Recovery v1.5

ogt zone recovery ea v1.5@amazing_owner.mq5

Похожие материалы по тегам

ares_indicator.pineTradingView · 1 общих теговgold_trend_revers.mq5MQL5 / MetaTrader 5 · 1 общих тегов!!!-mt4 x-xardg-rsi.mq5MQL5 / MetaTrader 5 · 1 общих тегов! cycle-identifier.mq5MQL5 / MetaTrader 5 · 1 общих тегов!!! rsi ma simple+arrows 1.2 (mtf).mq5MQL5 / MetaTrader 5 · 1 общих теговprecisionflowea.mq5MQL5 / MetaTrader 5 · 1 общих тегов
Вы автор или правообладатель?

Сообщите нам, если считаете, что материал размещён без разрешения.

Краткий обзор

О программе

OGT Zone Recovery v1.5 — торговый советник для MetaTrader 4, использующий анализ RSI на множестве таймфреймов для генерации сигналов входа в сделку. Советник реализует механизм «зонного восстановления»: после открытия начальной рыночной позиции размещается противоположный отложенный ордер в зоне восстановления. При срабатывании восстановления размер лота увеличивается и открывается новый противоположный отложенный ордер.

В качестве альтернативы фиксированным значениям доступна динамическая оценка зон и уровней тейк-профита на основе индикатора ATR. Встроена система управления рисками с возможностью расчёта размера позиции от процента риска на депозит или использования фиксированного лота с множителем и дополнениями. Предусмотрены 10 наборов пользовательских размеров лотов.

Советник поддерживает ежедневный торговый таймер с настройкой времени начала и окончания в серверном или локальном времени. Встроена визуальная торговая панель с кнопками управления и полями ввода параметров. Доступна фильтрация ордеров по магическому числу, ограничение максимального количества сделок и максимального убытка, а также симуляция комиссии при бэктестировании.

Настройки программы

НастройкаОписание
ZONE RECOVERY SETTINGS ** (RecoverySettings) ZONE RECOVERY SETTINGS — Заголовок группы настроек зонного восстановления.
Recovery Zone Size (points) (__RecoveryZoneSize__) Recovery Zone Size (points) — Размер зоны восстановления в пунктах.
Take Profit (points) (__TakeProfit__) Take Profit (points) — Тейк-профит начальной позиции в пунктах.
Max Trades (0 for unlimited) (MaxTrades) Max Trades — Максимальное количество одновременных сделок (0 — без ограничений).
Max Loss after Max Trades reached? (SetMaxLoss) Max Loss after Max Trades reached? — Включает ограничение убытка после достижения максимального количества сделок.
Max Loss after Max Trades (0 for unlimted) in deposit currency. (MaxLoss) Max Loss after Max Trades — Максимальный убыток в валюте депозита, при достижении которого позиции закрываются.
Use a Recovery Take Profit (UseRecoveryTakeProfit) Use a Recovery Take Profit — Включает отдельный тейк-профит для зоны восстановления.
Recovery Take Profit (points). (RecoveryTakeProfit) Recovery Take Profit (points) — Размер тейк-профита для зоны восстановления в пунктах.
Price for pending orders (__PendingPrice__) Price for pending orders — Цена для размещения отложенных ордеров.
ATR Dynamic Zone Sizing ** (ATRHeader) ATR Dynamic Zone Sizing — Заголовок группы настроек динамической оценки зон через ATR.
Use ATR? (UseATR) Use ATR? — Включает использование индикатора ATR для динамической оценки зон и тейк-профитов.
ATR Period (ATRPeriod) ATR Period — Период индикатора ATR для расчёта волатильности.
Fraction of ATR to use as Recovery Zone (ATRZoneFraction) Fraction of ATR to use as Recovery Zone — Доля ATR, используемая для определения размера зоны восстановления.
Fraction or ATR to use for TP sizes (ATRTPFraction) Fraction of ATR to use for TP sizes — Доля ATR, используемая для расчёта размера тейк-профита.
Fraction of ATR to use for recovery TP. (ATRRecoveryZone) Fraction of ATR to use for recovery TP — Доля ATR, используемая для определения размера зоны восстановления.
MONEY MANAGEMENT SETTINGS ** (MoneyManagement) MONEY MANAGEMENT SETTINGS — Заголовок группы настроек управления рисками и размера лота.
Account % Initial Lot Size (set to 0 if not used) (RiskPercent) Account % Initial Lot Size — Процент риска от депозита для расчёта размера лота (0 — не используется).
Initial Lot Size (if % not used) (InitialLotSize) Initial Lot Size — Начальный размер лота при отсутствии процентного риска.
Multiplier for Lots (LotMultiplier) Multiplier for Lots — Множитель для увеличения размера лота при каждом последующем шаге.
LotAdditions Lot Additions — Дополнительное значение, добавляемое к расчёту размера лота.
CUSTOM LOT SIZES ** (CustomLotSizing) CUSTOM LOT SIZING — Заголовок группы пользовательских размеров лотов.
CustomLotSize1 Custom Lot Size 1 — Пользовательский размер лота для первой сделки.
CustomLotSize2 Custom Lot Size 2 — Пользовательский размер лота для второй сделки.
CustomLotSize3 Custom Lot Size 3 — Пользовательский размер лота для третьей сделки.
CustomLotSize4 Custom Lot Size 4 — Пользовательский размер лота для четвёртой сделки.
CustomLotSize5 Custom Lot Size 5 — Пользовательский размер лота для пятой сделки.
CustomLotSize6 Custom Lot Size 6 — Пользовательский размер лота для шестой сделки.
CustomLotSize7 Custom Lot Size 7 — Пользовательский размер лота для седьмой сделки.
CustomLotSize8 Custom Lot Size 8 — Пользовательский размер лота для восьмой сделки.
CustomLotSize9 Custom Lot Size 9 — Пользовательский размер лота для девятой сделки.
CustomLotSize10 Custom Lot Size 10 — Пользовательский размер лота для десятой сделки.
TIMER SETTINGS ** (TimerSettings) TIMER SETTINGS — Заголовок группы настроек торгового таймера.
Use a Trade Timer? (UseTimer) Use a Trade Timer? — Включает ежедневный торговый таймер.
Start Hour (StartHour) Start Hour — Час начала торгового окна.
Start Minute (StartMinute) Start Minute — Минута начала торгового окна.
End Hour (EndHour) End Hour — Час окончания торгового окна.
End Minute (EndMinute) End Minute — Минута окончания торгового окна.
Use local time? (UseLocalTime) Use local time? — Использование локального времени вместо серверного для торгового таймера.
EA SETTINGS ** (TradeSettings) EA SETTINGS — Заголовок группы основных настроек советника.
EA_Mode EA Mode — Режим работы советника: ручной или сигналы RSI на множестве таймфреймов.
RSI Period (RSIPeriod) RSI Period — Период индикатора RSI для расчёта сигналов.
Over-bought level (OverboughtLevel) Over-bought level — Уровень перекупленности RSI для формирования сигнала на продажу.
Over-sold level (OversoldLevel) Over-sold level — Уровень перепроданности RSI для формирования сигнала на покупку.
Use M1 Timeframe? (UseM1Timeframe) Use M1 Timeframe? — Включает использование таймфрейма M1 для анализа RSI.
Use M5 Timeframe? (UseM5Timeframe) Use M5 Timeframe? — Включает использование таймфрейма M5 для анализа RSI.
Use M15 Timeframe? (UseM15Timeframe) Use M15 Timeframe? — Включает использование таймфрейма M15 для анализа RSI.
Use M30 Timeframe? (UseM30Timeframe) Use M30 Timeframe? — Включает использование таймфрейма M30 для анализа RSI.
Use H1 Timeframe? (UseH1Timeframe) Use H1 Timeframe? — Включает использование таймфрейма H1 для анализа RSI.
Use H4 Timeframe? (UseH4Timeframe) Use H4 Timeframe? — Включает использование таймфрейма H4 для анализа RSI.
Use Daily Timeframe? (UseDailyTimeframe) Use Daily Timeframe? — Включает использование таймфрейма D1 для анализа RSI.
Use Weekly Timeframe? (UseWeeklyTimeframe) Use Weekly Timeframe? — Включает использование таймфрейма W1 для анализа RSI.
Use Monthly Timeframe? (UseMonthlyTimeframe) Use Monthly Timeframe? — Включает использование таймфрейма MN1 для анализа RSI.
VISUALS ** (Visuals) VISUALS — Заголовок группы визуальных настроек.
profitLineColor Profit Line Color — Цвет линии уровня прибыли на графике.
Panel X coordinate. (Panel_X) Panel X coordinate — Горизонтальная позиция торговой панели на графике.
Panel Y coordinate. (Panel_Y) Panel Y coordinate — Вертикальная позиция торговой панели на графике.
Panel background colour. (Panel_Color) Panel background colour — Цвет фона торговой панели.
Panel lable text color. (Panel_Lable_Color) Panel label text color — Цвет текста меток на торговой панели.
OTHER SETTINGS ** (BacktestingSettings) OTHER SETTINGS — Заголовок группы настроек бэктестирования.
Magic Number (MagicNumber) Magic Number — Магический номер для идентификации ордеров советника.
Slippage Max (Points). (Slippage) Slippage Max (Points) — Максимально допустимое проскальзывание в пунктах.
Trade on New Bar? (TradeOnBarOpen) Trade on New Bar? — Открытие сделок только при появлении нового бара.
Back tester speed (speed) Back tester speed — Скорость прохождения бэктеста.
Back tester simulated commission (TestCommission) Back tester simulated commission — Симулированная комиссия для расчётов при бэктестировании.
Получить полный код

Поиск по коду файла

#define MODE_TICKVALUE 16
#define MODE_TICKSIZE 17
#define SELECT_BY_POS 0
#define OP_BUY 0
#define MODE_SPREAD 13
#define OP_SELL 1
#define MODE_ASK 10
#define SELECT_BY_TICKET 1
#define OP_BUYSTOP 4
#define MODE_BID 9
#define OP_SELLSTOP 5
#define OP_BUYLIMIT 2
#define OP_SELLLIMIT 3
#define MODE_DIGITS 12
#define ERR_BROKER_BUSY 137
#define ERR_COMMON_ERROR 2
#define ERR_NO_ERROR 0
#define ERR_NO_CONNECTION 6
#define ERR_NO_RESULT 1
#define ERR_SERVER_BUSY 4
#define ERR_NOT_ENOUGH_RIGHTS 7
#define ERR_MALFUNCTIONAL_TRADE 9
#define ERR_TRADE_CONTEXT_BUSY 146
#define ERR_TRADE_TIMEOUT 128
#define ERR_REQUOTE 138
#define ERR_TOO_MANY_REQUESTS 141
#define ERR_OFF_QUOTES 136
#define ERR_PRICE_CHANGED 135
#define ERR_TOO_FREQUENT_REQUESTS 8

#property description   "Coded by: A Sweeney"

#property strict

enum EA_Setting {Manual, RSI_MTF};

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

input string RecoverySettings; // ** ZONE RECOVERY SETTINGS **
input int __RecoveryZoneSize__ = 200; // Recovery Zone Size (points)
int RecoveryZoneSize = __RecoveryZoneSize__;
input int __TakeProfit__ = 200; // Take Profit (points)
int TakeProfit = __TakeProfit__;
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).
input double __PendingPrice__ = 0; // Price for pending orders
double PendingPrice = __PendingPrice__;

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 = false; // Use M1 Timeframe?
input bool UseM5Timeframe = false; // Use M5 Timeframe?
input bool UseM15Timeframe = true; // Use M15 Timeframe?
input bool UseM30Timeframe = true; // 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

#define EA_NAME "OGT Zone Recovery v1.5"
#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;

void OnInit()
{
      // код доступен только после оплаты
   }

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;
      }  
   }
}

void __OnTick__()
{
   if(CCBC::IsVisualMode() == true)
   {
      int Waitloop = 0;
      while(Waitloop < speed)
      {
         Waitloop++;
      }
   }

   bool tradeEnabled = true;
   if(UseTimer == true)
   {
      tradeEnabled = CheckDailyTimer();
   }

   bool newBar = true;
   int barShift = 0;

   if(TradeOnBarOpen == true)
   {
      newBar = false;
      datetime time[];
      bool firstRun = false;

      CCBC::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;
   }

   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 = CCBC::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);
   }

   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)
   {

      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*CCBC::MarketInfo(_Symbol, MODE_TICKVALUE)/CCBC::MarketInfo(_Symbol, MODE_TICKSIZE);

      for(int counter = 0; counter <= CCBC::OrdersTotal() - 1; counter++)
      {
         if(CCBC::OrderSelect(counter, SELECT_BY_POS))
         {
            if(CCBC::OrderMagicNumber() == MagicNumber && CCBC::OrderSymbol() == Symbol())
            {
               positions += 1;
               currentProfit += CCBC::OrderProfit();

               if(CCBC::OrderType() == OP_BUY)
               {
                  positionSize += (CCBC::OrderOpenPrice()*CCBC::OrderLots());
                  netLotSize += CCBC::OrderLots();
                  totalSpreadCosts += (CCBC::OrderLots()*CCBC::MarketInfo(_Symbol, MODE_SPREAD)*point_value);
                  totalCommision += CCBC::OrderCommission();
               }
               else if(CCBC::OrderType() == OP_SELL)
               {
                  positionSize -= (CCBC::OrderOpenPrice()*CCBC::OrderLots());
                  netLotSize -= CCBC::OrderLots();
                  totalSpreadCosts += (CCBC::OrderLots()*CCBC::MarketInfo(_Symbol, MODE_SPREAD)*point_value);
                  totalCommision += CCBC::OrderCommission();
               }
            }
         }
      }

      double volume;
      if(CustomLotSize1 != 0) volume = CustomLotSize1;
      else volume = gInitialLotSize;
      double profitTarget = RecoveryTakeProfit*point_value*volume;
      if(UseATR == true) 
      {
         double atr = CCBC::iATR(_Symbol, PERIOD_D1, ATRPeriod, 1);
         profitTarget = (ATRRecoveryZone*atr*point_value*volume)/_Point;
      }

      double tradeCosts = 0;
      if(CCBC::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: ", CCBC::DoubleToStr(profitTarget, 2), "$ exceeded at: ", CCBC::DoubleToStr(currentProfit, 2), "$, Costs(", CCBC::DoubleToStr(tradeCosts, 2), "$)");        
      }
      if(netLotSize != 0)
      {
         averagePrice = NormalizeDouble(positionSize/netLotSize, _Digits);
         Comment(CCBC::StringConcatenate("Average Price: ", CCBC::DoubleToStr(averagePrice, _Digits), ", Profit Target: $", CCBC::DoubleToStr(profitTarget, 2), " + Trade Costs: $", CCBC::DoubleToStr(tradeCosts, 2), ", Running Profit:  $", CCBC::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);
      }   

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

      if(gCurrentDirection == 1)
      {
         double price = CCBC::MarketInfo(Symbol(), MODE_ASK);
         if(CCBC::OrderSelect(gSellStopTicket, SELECT_BY_TICKET))
         {
            if(CCBC::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

               gLotSize = GetTradeVolume(positions+1);

               if(MaxTrades == 0 || positions < MaxTrades) // check we've not exceeded the max trades
               {

                 gBuyStopTicket = OpenPendingOrder(Symbol(), OP_BUYSTOP, gLotSize, gBuyOpenPrice, 0, 0, CCBC::StringConcatenate("Recovery Buy Stop opened."), 0, clrTurquoise); // create an opposite buy stop
                 gRecoveryInitiated = true; // signal that we are in recovery mode
               }

               gCurrentDirection = -1;            
            }
         } else {
            string message = "Warning - EA could not find the recovery Sell Stop";
            Alert(message);
            Print(message);
         }
      }

      if(gCurrentDirection == -1)
      {
         double price = CCBC::MarketInfo(Symbol(), MODE_BID);   
         if(CCBC::OrderSelect(gBuyStopTicket, SELECT_BY_TICKET))
         {
            if(CCBC::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

               gLotSize = GetTradeVolume(positions+1);               

               if(MaxTrades == 0 || positions < MaxTrades) // check we've not exceeded the max trades
               {

                  gSellStopTicket = OpenPendingOrder(Symbol(), OP_SELLSTOP, gLotSize, gSellOpenPrice, 0, 0, CCBC::StringConcatenate("Recovery Sell Stop opened."), 0, clrPink); // create an opposite sell stop
                  gRecoveryInitiated = true; // signal we're in recovery mode
               }

               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");
   }
}

void TakeTrade(int direction)
{

    double tp = 0;
    double rz = 0;

    if(UseATR == true)
    {
      double atr = CCBC::iATR(_Symbol, PERIOD_D1, ATRPeriod, 1);
      tp = atr*ATRTPFraction;
      rz = atr*ATRZoneFraction;

    } 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(CCBC::OrderSelect(gBuyTicket, SELECT_BY_TICKET))
       {                 
          gBuyOpenPrice = CCBC::OrderOpenPrice();       
          gSellOpenPrice = NormalizeDouble((gBuyOpenPrice - rz), _Digits);
          gBuyTakeProfit = NormalizeDouble((gBuyOpenPrice + tp), _Digits);
          gSellTakeProfit = NormalizeDouble((gBuyOpenPrice - (tp + rz)), _Digits);

          gLotSize = GetTradeVolume(2);
          gSellStopTicket = OpenPendingOrder(Symbol(), OP_SELLSTOP, gLotSize, gSellOpenPrice, 0, 0, "Initial Recovery Sell Stop)", 0, clrPink);
          gCurrentDirection = direction;
          price = gBuyOpenPrice;
       }
   }

   else if(direction == -1)
   {
       gSellTicket = OpenMarketOrder(Symbol(), OP_SELL, gLotSize, "Initial Sell Order", clrRed);
       if(CCBC::OrderSelect(gSellTicket, SELECT_BY_TICKET))
       {
          gSellOpenPrice = CCBC::OrderOpenPrice(); 
          gBuyOpenPrice = NormalizeDouble((gSellOpenPrice + rz), _Digits);
          gSellTakeProfit = NormalizeDouble((gSellOpenPrice - tp), _Digits);
          gBuyTakeProfit = NormalizeDouble((gSellOpenPrice + (tp + rz)), _Digits);

          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(UseATR == true)
    {
      double atr = CCBC::iATR(_Symbol, PERIOD_D1, ATRPeriod, 1);
      tp = atr*ATRTPFraction;
      rz = atr*ATRZoneFraction;

    } 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);
}

int Is_RSI_OBOS_on_MTF(int shift)
{
   int direction = 0;

   double rsi = CCBC::iRSI(_Symbol, PERIOD_M1, RSIPeriod, PRICE_CLOSE, shift);
   if((UseM1Timeframe == false) || (rsi < OversoldLevel))
   {
      rsi = CCBC::iRSI(_Symbol, PERIOD_M5, RSIPeriod, PRICE_CLOSE, shift);
      if(UseM5Timeframe == false || (rsi < OversoldLevel))
      {
         rsi = CCBC::iRSI(_Symbol, PERIOD_M15, RSIPeriod, PRICE_CLOSE, shift);
         if((UseM15Timeframe == false) || (rsi < OversoldLevel))
         {
            rsi = CCBC::iRSI(_Symbol, PERIOD_M30, RSIPeriod, PRICE_CLOSE, shift);
            if((UseM30Timeframe == false) || (rsi < OversoldLevel))
            {
               rsi = CCBC::iRSI(_Symbol, PERIOD_H1, RSIPeriod, PRICE_CLOSE, shift);
               if((UseH1Timeframe == false) || (rsi < OversoldLevel))
               {
                  rsi = CCBC::iRSI(_Symbol, PERIOD_H4, RSIPeriod, PRICE_CLOSE, shift);
                  if((UseH4Timeframe == false) || (rsi < OversoldLevel))
                  {
                     rsi = CCBC::iRSI(_Symbol, PERIOD_D1, RSIPeriod, PRICE_CLOSE, shift);
                     if((UseDailyTimeframe == false) || (rsi < OversoldLevel))
                     {
                        rsi = CCBC::iRSI(_Symbol, PERIOD_W1, RSIPeriod, PRICE_CLOSE, shift);
                        if((UseWeeklyTimeframe == false) || (rsi < OversoldLevel))
                        {
                           rsi = CCBC::iRSI(_Symbol, PERIOD_MN1, RSIPeriod, PRICE_CLOSE, shift);
                           if((UseMonthlyTimeframe == false) || (rsi < OversoldLevel))
                           {
                              direction = 1;
                              return direction;
                           }
                        }
                     }                     
                  }
               }
            }
         }
      }
   }

   rsi = CCBC::iRSI(_Symbol, PERIOD_M1, RSIPeriod, PRICE_CLOSE, shift);
   if((UseM1Timeframe == false) || (rsi > OverboughtLevel))
   {
      rsi = CCBC::iRSI(_Symbol, PERIOD_M5, RSIPeriod, PRICE_CLOSE, shift);
      if(UseM5Timeframe == false || (rsi > OverboughtLevel))
      {
         rsi = CCBC::iRSI(_Symbol, PERIOD_M15, RSIPeriod, PRICE_CLOSE, shift);
         if((UseM15Timeframe == false) || (rsi > OverboughtLevel))
         {
            rsi = CCBC::iRSI(_Symbol, PERIOD_M30, RSIPeriod, PRICE_CLOSE, shift);
            if((UseM30Timeframe == false) || (rsi > OverboughtLevel))
            {
               rsi = CCBC::iRSI(_Symbol, PERIOD_H1, RSIPeriod, PRICE_CLOSE, shift);
               if((UseH1Timeframe == false) || (rsi > OverboughtLevel))
               {
                  rsi = CCBC::iRSI(_Symbol, PERIOD_H4, RSIPeriod, PRICE_CLOSE, shift);
                  if((UseH4Timeframe == false) || (rsi > OverboughtLevel))
                  {
                     rsi = CCBC::iRSI(_Symbol, PERIOD_D1, RSIPeriod, PRICE_CLOSE, shift);
                     if((UseDailyTimeframe == false) || (rsi > OverboughtLevel))
                     {
                        rsi = CCBC::iRSI(_Symbol, PERIOD_W1, RSIPeriod, PRICE_CLOSE, shift);
                        if((UseWeeklyTimeframe == false) || (rsi > OverboughtLevel))
                        {
                           rsi = CCBC::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);
   }
   CCBC::ObjectCreate(0, PROFIT_LINE, OBJ_HLINE, 0,0,price);
   CCBC::ObjectSetInteger(0, PROFIT_LINE, OBJPROP_COLOR, profitLineColor);
   CCBC::ObjectSetInteger(0, PROFIT_LINE, OBJPROP_STYLE, STYLE_DASH);
}

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

void CreateTradingPanel()
{

   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";   
   CCBC::ObjectCreate(0, buttonBox, OBJ_RECTANGLE_LABEL, 0, 0, 0);
   CCBC::ObjectSetInteger(0,buttonBox,OBJPROP_CORNER,CORNER_LEFT_UPPER);
   CCBC::ObjectSetInteger(0, buttonBox, OBJPROP_XSIZE, panelWidth);
   CCBC::ObjectSetInteger(0, buttonBox, OBJPROP_YSIZE, panelHeight);
   CCBC::ObjectSetInteger(0, buttonBox, OBJPROP_XDISTANCE, panelX);
   CCBC::ObjectSetInteger(0, buttonBox, OBJPROP_YDISTANCE, panelY);
   CCBC::ObjectSetInteger(0, buttonBox, OBJPROP_BGCOLOR, Panel_Color);
   CCBC::ObjectSetInteger(0,buttonBox,OBJPROP_BORDER_TYPE,BORDER_RAISED);
   CCBC::ObjectSetInteger(0,buttonBox,OBJPROP_COLOR,clrGray);
   CCBC::ObjectSetInteger(0,buttonBox,OBJPROP_SELECTABLE,false);
   CCBC::ObjectSetInteger(0,buttonBox,OBJPROP_HIDDEN,false);
   CCBC::ObjectSetInteger(0,buttonBox,OBJPROP_ZORDER,0);
   gTradingPanelObjects[0] = buttonBox;

   string panelLabel = "Trading Panel Label";
   CCBC::ObjectCreate(0, panelLabel, OBJ_LABEL, 0,0,0);
   CCBC::ObjectSetString(0, panelLabel, OBJPROP_TEXT, EA_NAME);
   CCBC::ObjectSetInteger(0, panelLabel, OBJPROP_XDISTANCE, lableX);
   CCBC::ObjectSetInteger(0, panelLabel, OBJPROP_YDISTANCE, lableY);
   CCBC::ObjectSetInteger(0, panelLabel, OBJPROP_COLOR, Panel_Lable_Color);
   CCBC::ObjectSetInteger(0, panelLabel, OBJPROP_FONTSIZE, 9);
   gTradingPanelObjects[1] = panelLabel;

   string sellButtonName = SELL_BUTTON;  
   CCBC::ObjectCreate(0, sellButtonName, OBJ_BUTTON, 0, 0, 0);
   CCBC::ObjectSetInteger(0, sellButtonName, OBJPROP_XSIZE, buttonWidth);
   CCBC::ObjectSetInteger(0, sellButtonName, OBJPROP_YSIZE, buttonHeight);
   CCBC::ObjectSetInteger(0, sellButtonName, OBJPROP_XDISTANCE, buttonX);
   CCBC::ObjectSetInteger(0, sellButtonName, OBJPROP_YDISTANCE, buttonY);
   CCBC::ObjectSetInteger(0, sellButtonName, OBJPROP_COLOR, Panel_Lable_Color);
   CCBC::ObjectSetInteger(0, sellButtonName, OBJPROP_BGCOLOR, clrRed);
   CCBC::ObjectSetString(0, sellButtonName, OBJPROP_TEXT, "Sell");
   gTradingPanelObjects[2] = SELL_BUTTON;

   string buyButtonName = BUY_BUTTON;
   CCBC::ObjectCreate(0, buyButtonName, OBJ_BUTTON, 0, 0, 0);
   CCBC::ObjectSetInteger(0, buyButtonName, OBJPROP_XSIZE, buttonWidth);
   CCBC::ObjectSetInteger(0, buyButtonName, OBJPROP_YSIZE, buttonHeight);
   CCBC::ObjectSetInteger(0, buyButtonName, OBJPROP_XDISTANCE, (buttonX+buttonWidth+boxMargin));
   CCBC::ObjectSetInteger(0, buyButtonName, OBJPROP_YDISTANCE, buttonY);
   CCBC::ObjectSetInteger(0, buyButtonName, OBJPROP_COLOR, Panel_Lable_Color);
   CCBC::ObjectSetInteger(0, buyButtonName, OBJPROP_BGCOLOR, clrGreen);
   CCBC::ObjectSetString(0, buyButtonName, OBJPROP_TEXT, "Buy");
   gTradingPanelObjects[3] = BUY_BUTTON; 

   CCBC::ObjectCreate(0, CLOSE_ALL_BUTTON, OBJ_BUTTON, 0, 0, 0);
   CCBC::ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_XSIZE, buttonWidth+boxMargin+buttonWidth);
   CCBC::ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_YSIZE, buttonHeight);
   CCBC::ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_XDISTANCE, (buttonX));
   CCBC::ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_YDISTANCE, buttonY+buttonHeight+boxMargin);
   CCBC::ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_COLOR, Panel_Lable_Color);
   CCBC::ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_BGCOLOR, clrGray);
   CCBC::ObjectSetString(0, CLOSE_ALL_BUTTON, OBJPROP_TEXT, "Close All Orders");
   gTradingPanelObjects[4] = CLOSE_ALL_BUTTON;

   string TPLabel = "TP Label";
   CCBC::ObjectCreate(0, TPLabel, OBJ_LABEL, 0, 0, 0);
   CCBC::ObjectSetString(0, TPLabel, OBJPROP_TEXT, "TP: ");
   CCBC::ObjectSetInteger(0, TPLabel, OBJPROP_XDISTANCE, buttonX);
   CCBC::ObjectSetInteger(0, TPLabel, OBJPROP_YDISTANCE, 5+buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin);
   CCBC::ObjectSetInteger(0, TPLabel, OBJPROP_COLOR, Panel_Lable_Color);
   gTradingPanelObjects[5] = TPLabel;

   string zoneLable = "Zone Lable";
   CCBC::ObjectCreate(0, zoneLable, OBJ_LABEL, 0, 0, 0);
   CCBC::ObjectSetString(0, zoneLable, OBJPROP_TEXT, "Zone: ");
   CCBC::ObjectSetInteger(0, zoneLable, OBJPROP_XDISTANCE, buttonX);
   CCBC::ObjectSetInteger(0, zoneLable, OBJPROP_YDISTANCE, 5+ buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin);
   CCBC::ObjectSetInteger(0, zoneLable, OBJPROP_COLOR, Panel_Lable_Color);
   gTradingPanelObjects[6] = zoneLable;

   CCBC::ObjectCreate(0, TP_EDIT, OBJ_EDIT, 0, 0, 0);
   CCBC::ObjectSetInteger(0, TP_EDIT, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   CCBC::ObjectSetInteger(0, TP_EDIT, OBJPROP_XDISTANCE, buttonX+buttonWidth+boxMargin);
   CCBC::ObjectSetInteger(0, TP_EDIT, OBJPROP_YDISTANCE, buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin);
   CCBC::ObjectSetInteger(0, TP_EDIT, OBJPROP_XSIZE, buttonWidth);
   CCBC::ObjectSetInteger(0, TP_EDIT, OBJPROP_YSIZE, buttonHeight);   
   CCBC::ObjectSetInteger(0, TP_EDIT, OBJPROP_COLOR, clrBlack);
   CCBC::ObjectSetInteger(0, TP_EDIT, OBJPROP_BGCOLOR, clrWhite);
   CCBC::ObjectSetString(0, TP_EDIT, OBJPROP_TEXT, IntegerToString(TakeProfit));
   CCBC::ObjectSetInteger(0,TP_EDIT,OBJPROP_ALIGN,ALIGN_CENTER);
   gTradingPanelObjects[7] = TP_EDIT;

   CCBC::ObjectCreate(0, ZONE_EDIT, OBJ_EDIT, 0, 0, 0);
   CCBC::ObjectSetInteger(0, ZONE_EDIT, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   CCBC::ObjectSetInteger(0, ZONE_EDIT, OBJPROP_XDISTANCE, buttonX+buttonWidth+boxMargin);
   CCBC::ObjectSetInteger(0, ZONE_EDIT, OBJPROP_YDISTANCE, buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin);   
   CCBC::ObjectSetInteger(0, ZONE_EDIT, OBJPROP_XSIZE, buttonWidth);
   CCBC::ObjectSetInteger(0, ZONE_EDIT, OBJPROP_YSIZE, buttonHeight);
   CCBC::ObjectSetInteger(0, ZONE_EDIT, OBJPROP_COLOR, clrBlack);
   CCBC::ObjectSetInteger(0, ZONE_EDIT, OBJPROP_BGCOLOR, clrWhite);
   CCBC::ObjectSetString(0, ZONE_EDIT, OBJPROP_TEXT, IntegerToString(RecoveryZoneSize));
   CCBC::ObjectSetInteger(0,ZONE_EDIT,OBJPROP_ALIGN,ALIGN_CENTER);
   gTradingPanelObjects[8] = ZONE_EDIT;

   CCBC::ObjectCreate(0, PENDING_EDIT, OBJ_EDIT, 0, 0, 0);
   CCBC::ObjectSetInteger(0, PENDING_EDIT, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   CCBC::ObjectSetInteger(0, PENDING_EDIT, OBJPROP_XDISTANCE, buttonX+buttonWidth+boxMargin);
   CCBC::ObjectSetInteger(0, PENDING_EDIT, OBJPROP_YDISTANCE, buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin);   
   CCBC::ObjectSetInteger(0, PENDING_EDIT, OBJPROP_XSIZE, buttonWidth);
   CCBC::ObjectSetInteger(0, PENDING_EDIT, OBJPROP_YSIZE, buttonHeight);
   CCBC::ObjectSetInteger(0, PENDING_EDIT, OBJPROP_COLOR, clrBlack);
   CCBC::ObjectSetInteger(0, PENDING_EDIT, OBJPROP_BGCOLOR, clrWhite);
   CCBC::ObjectSetString(0, PENDING_EDIT, OBJPROP_TEXT, IntegerToString(pending));
   CCBC::ObjectSetInteger(0,PENDING_EDIT,OBJPROP_ALIGN,ALIGN_CENTER);
   gTradingPanelObjects[9] = PENDING_EDIT;

   string pendingLabel = "Pending Label";
   CCBC::ObjectCreate(0, pendingLabel, OBJ_LABEL, 0, 0, 0);
   CCBC::ObjectSetString(0, pendingLabel, OBJPROP_TEXT, "Price: ");
   CCBC::ObjectSetInteger(0, pendingLabel, OBJPROP_XDISTANCE, buttonX);
   CCBC::ObjectSetInteger(0, pendingLabel, OBJPROP_YDISTANCE, 5+ buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin);
   CCBC::ObjectSetInteger(0, pendingLabel, OBJPROP_COLOR, Panel_Lable_Color);
   gTradingPanelObjects[10] = pendingLabel;  

}

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 = CCBC::ObjectGetString(0, TP_EDIT, OBJPROP_TEXT);
      TakeProfit = StringToPips(takeProfitString);
   }
   else if(id == CHARTEVENT_OBJECT_ENDEDIT && sparam == ZONE_EDIT)
   {
      string zoneString = CCBC::ObjectGetString(0, ZONE_EDIT, OBJPROP_TEXT);
      RecoveryZoneSize = StringToPips(zoneString);
   }
   else if(id == CHARTEVENT_OBJECT_ENDEDIT && sparam == PENDING_EDIT)
   {
      string pendingString = CCBC::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];
         CCBC::ObjectDelete(0, objectName);
      }
   }
}

double PipPoint(string Currency)
   {
      double CalcPoint = 0; 
      double CalcDigits = CCBC::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)CCBC::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 = CCBC::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 <= CCBC::OrdersTotal()-1; Counter++)
   {
      if(CCBC::OrderSelect(Counter,SELECT_BY_POS))
      {
         if(CCBC::OrderMagicNumber() == MagicNumber && CCBC::OrderSymbol() == _Symbol && (CCBC::OrderType() == OP_BUY || CCBC::OrderType() == OP_SELL))
         {

            int CloseTicket = CCBC::OrderTicket();
            double CloseLots = CCBC::OrderLots();
            while(CCBC::IsTradeContextBusy()) Sleep(10);

            CCBC::RefreshRates();            
            double ClosePrice = CCBC::MarketInfo(_Symbol,MODE_BID);
            if(CCBC::OrderType() == OP_SELL) ClosePrice = CCBC::MarketInfo(_Symbol, MODE_ASK);

            bool Closed = CCBC::OrderClose(CloseTicket,CloseLots,ClosePrice,Slippage,Red);

            if(Closed == false)
            {
               int ErrorCode = CCBC::GetLastError();
               string ErrAlert = CCBC::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;
}

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;

   for(int order = 0; order <= CCBC::OrdersTotal() - 1; order++)
   {

      bool result = CCBC::OrderSelect(order,SELECT_BY_POS);

      int orderType = CCBC::OrderType();
      int orderMagicNumber = CCBC::OrderMagicNumber();
      int orderTicket = CCBC::OrderTicket();
      double orderVolume = CCBC::OrderLots();

      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;

      if(deleteOrder == true && orderMagicNumber == MagicNumber)
      {
         result = CCBC::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;

	while(retryCount <= max_attempts)
	{
		while(CCBC::IsTradeContextBusy()) Sleep(10);
		ticket = CCBC::OrderSend(pSymbol, pType, pVolume, pPrice, Slippage, pStop, pProfit, pComment, MagicNumber, pExpiration, pArrow);

   	if(ticket == -1)
   	{
   		errorCode = CCBC::GetLastError();
   		bool checkError = RetryOnError(errorCode);

      	if(checkError == false)  
   		{
     			Alert("Open ",orderType," order: Error ",errorCode,".");
     			Print("Symbol: ",pSymbol,", Volume: ",pVolume,", Price: ",pPrice,", SL: ",pStop,", TP: ",pProfit,", Expiration: ",pExpiration);
   			break;
   		}

   		else
   		{
   			Print("Server error detected, retrying...");
   			Sleep(3000);
   			retryCount++;
   		}
   	}

   	else
   	{
   	   Comment(orderType," order #",ticket," opened on ",_Symbol);
   	   Print(orderType," order #",ticket," opened on ",_Symbol);
   	   break;
   	} 
   }

	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)
{

	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;

	while(retryCount <= max_attempts) 
	{
		while(CCBC::IsTradeContextBusy()) Sleep(10);

		if(pType == OP_BUY) orderPrice = CCBC::MarketInfo(pSymbol,MODE_ASK);
		else if(pType == OP_SELL) orderPrice = CCBC::MarketInfo(pSymbol,MODE_BID);

		ticket = CCBC::OrderSend(pSymbol,pType,pVolume,orderPrice,Slippage,0,0,pComment,MagicNumber,0,pArrow);

		if(ticket == -1)
		{
			errorCode = CCBC::GetLastError();
			bool checkError = RetryOnError(errorCode);

			if(checkError == false)
			{
				Alert("Open ",orderType," order: Error ",errorCode,".");
				Print("Symbol: ",pSymbol,", Volume: ",pVolume,", Price: ",orderPrice);
				break;
			}

			else
			{
				Print("Server error detected, retrying...");
				Sleep(wait_time);
				retryCount++;
			}
		}

		else
		{
		   Comment(orderType," order #",ticket," opened on ",pSymbol);
		   Print(orderType," order #",ticket," opened on ",pSymbol);
		   break;
		} 
   }

	if(retryCount > max_attempts)
	{
		Alert("Open ",orderType," order: Max retries exceeded. Error ",errorCode," - ",errDesc);
		Print("Symbol: ",pSymbol,", Volume: ",pVolume,", Price: ",orderPrice);
	}

   return(ticket);
} 

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);
	}

	return NULL;
}

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);
}

bool CheckDailyTimer()
{
   datetime TimeStart = CreateDateTime(StartHour, StartMinute);
   datetime TimeEnd = CreateDateTime(EndHour, EndMinute);

   datetime currentTime;
	if(UseLocalTime == true) currentTime = TimeLocal();
	else currentTime = TimeCurrent();

	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 <= CCBC::OrdersTotal()-1; Counter++)
   {
      if(CCBC::OrderSelect(Counter,SELECT_BY_POS))
      {
         if(CCBC::OrderMagicNumber() == MagicNumber && CCBC::OrderSymbol() == _Symbol && (CCBC::OrderType() == OP_BUY || CCBC::OrderType() == OP_SELL))
         {
            open_orders++;
            if(CCBC::OrderLots() > largest_lots)
            { 
               ticket = CCBC::OrderTicket();
               largest_lots = CCBC::OrderLots();
            }
         }
         if(CCBC::OrderMagicNumber() == MagicNumber && CCBC::OrderSymbol() == _Symbol && CCBC::OrderType() == OP_BUYSTOP)
         {
            gBuyStopTicket = CCBC::OrderTicket();
            stopTicket = gBuyStopTicket;
         } else if(CCBC::OrderMagicNumber() == MagicNumber && CCBC::OrderSymbol() == _Symbol && CCBC::OrderType() == OP_SELLSTOP)
         {
            gSellStopTicket = CCBC::OrderTicket();
            stopTicket = gSellStopTicket;
         }
      }
   }

   if(ticket > 0)
   {
      if(CCBC::OrderSelect(ticket, SELECT_BY_TICKET))
      {
         int type = CCBC::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 FXD_SELECTED_TYPE = 0;// Indicates what is selected by OrderSelect, 1 for trade, 2 for pending order, 3 for history trade
ulong FXD_SELECTED_TICKET = 0;// The ticket number selected by OrderSelect
int FXD_INDICATOR_COUNTED_MEMORY = 0;// Used as a memory for IndicatorCounted() function. It needs to be outside of the function, because when OnCalculate needs to be reset, this memory must be reset as well.

int Bars     = Bars(_Symbol, PERIOD_CURRENT);
int Digits   = _Digits;
double Point = _Point;
double Ask, Bid, Close[], High[], Low[], Open[];
long Volume[];
datetime Time[];

void OnTick()
{
      // код доступен только после оплаты
   }

class CCBC
{
private:
	/**
	* _LastError is used to set custom errors that could be returned by the custom GetLastError method
	* The initial value should be -1 and everything >= 0 should be valid error code
	* When setting an error code in it, it should be the MQL5 value,
	* because then in GetLastError it will be converted to MQL4 value
	*/
	static int _LastError;
public:
	CCBC() {

	};

	/**
	* Overloads for the case when numeric value is used for timeframe
	*/
	static int CopyTime(const string symbol_name, int timeframe, int start_pos, int count, datetime &time_array[]) {
		return ::CopyTime(symbol_name, CCBC::_ConvertTimeframe_(timeframe), start_pos, count, time_array);
	}
	static int CopyTime(const string symbol_name, int timeframe, datetime start_time, int count, datetime &time_array[]) {
		return ::CopyTime(symbol_name, CCBC::_ConvertTimeframe_(timeframe), start_time, count, time_array);
	}
	static int CopyTime(const string symbol_name, int timeframe, datetime start_time, datetime stop_time, datetime &time_array[]) {
		return ::CopyTime(symbol_name, CCBC::_ConvertTimeframe_(timeframe), start_time, stop_time, time_array);
	}

	static string DoubleToStr(double value, int digits = 8) {
		return ::DoubleToString(value, digits);
	}

	/**
	* In MQL4's documentation errors are also shown as numeric values and sometimes people use these numbers, because they are shorter to write.
	* This means that GetLastError shoud return such MQL4 numeric values instead of the MQL5 values.
	* Supports custom error codes that can be set with CCBC -> _LastError
	*/
	static int GetLastError() {
		int errorCode = 0;

		if (CCBC::_LastError >= 0) {
			errorCode = CCBC::_LastError;
			CCBC::_LastError = -1;
		}
		else {
			errorCode = ::GetLastError();
		}

		switch (errorCode) {

			case ERR_SUCCESS                       : return 0; /* ERR_NO_ERROR */

			case TRADE_RETCODE_INVALID             : return 3; /* ERR_INVALID_TRADE_PARAMETERS */
			case ERR_TRADE_SEND_FAILED             : return 4; /* ERR_SERVER_BUSY */

			case TRADE_RETCODE_CONNECTION          : return 6; /* ERR_NO_CONNECTION */
			case TRADE_RETCODE_REJECT              : return 7; /* ERR_NOT_ENOUGH_RIGHTS */

			case TRADE_RETCODE_ERROR               : return 9; /* ERR_MALFUNCTIONAL_TRADE */

			case TRADE_RETCODE_TIMEOUT             : return 128; /* ERR_TRADE_TIMEOUT */
			case TRADE_RETCODE_INVALID_PRICE       : return 129; /* ERR_INVALID_PRICE */
			case TRADE_RETCODE_INVALID_STOPS       : return 130; /* ERR_INVALID_STOPS */
			case TRADE_RETCODE_INVALID_VOLUME      : return 131; /* ERR_INVALID_TRADE_VOLUME */
			case TRADE_RETCODE_MARKET_CLOSED       : return 132; /* ERR_MARKET_CLOSED */
			case TRADE_RETCODE_TRADE_DISABLED      : return 133; /* ERR_TRADE_DISABLED */
			case TRADE_RETCODE_NO_MONEY            : return 134; /* ERR_NOT_ENOUGH_MONEY */
			case TRADE_RETCODE_PRICE_CHANGED       : return 135; /* ERR_PRICE_CHANGED */
			case TRADE_RETCODE_PRICE_OFF           : return 136; /* ERR_OFF_QUOTES */

			case TRADE_RETCODE_REQUOTE             : return 138; /* ERR_REQUOTE */
			case TRADE_RETCODE_LOCKED              : return 139; /* ERR_ORDER_LOCKED */

			case TRADE_RETCODE_TOO_MANY_REQUESTS   : return 141; /* ERR_TOO_MANY_REQUESTS */

			case TRADE_RETCODE_INVALID_EXPIRATION  : return 147; /* ERR_TRADE_EXPIRATION_DENIED */
			case TRADE_RETCODE_LIMIT_ORDERS        : return 148; /* ERR_TRADE_TOO_MANY_ORDERS */

			case 10046                             : return 149; /* ERR_TRADE_HEDGE_PROHIBITED */
			case TRADE_RETCODE_FIFO_CLOSE          : return 150; /* ERR_TRADE_PROHIBITED_BY_FIFO */

			case ERR_INVALID_POINTER_TYPE          : return 4001; /* ERR_WRONG_FUNCTION_POINTER */
			case ERR_SMALL_ARRAY                   : return 4002; /* ERR_ARRAY_INDEX_OUT_OF_RANGE */

			case ERR_MATH_OVERFLOW                 : return 4004; /* ERR_RECURSIVE_STACK_OVERFLOW */

			case ERR_STRING_OUT_OF_MEMORY          : return 4006; /* ERR_NO_MEMORY_FOR_PARAM_STRING */

			case ERR_NOTINITIALIZED_STRING         : return 4008; /* ERR_NOT_INITIALIZED_STRING */

			case ERR_STRING_TOO_BIGNUMBER          : return 4011; /* ERR_TOO_LONG_STRING */

			case ERR_ZEROSIZE_ARRAY                : return 4016; /* ERR_NOT_INITIALIZED_ARRAY */

			case ERR_INTERNAL_ERROR                : return 4024; /* ERR_INTERNAL_ERROR */
			case ERR_NOT_ENOUGH_MEMORY             : return 4025; /* ERR_OUT_OF_MEMORY */
			case ERR_INVALID_POINTER               : return 4026; /* ERR_INVALID_POINTER */
			case ERR_TOO_MANY_FORMATTERS           : return 4027; /* ERR_FORMAT_TOO_MANY_FORMATTERS */
			case ERR_TOO_MANY_PARAMETERS           : return 4028; /* ERR_FORMAT_TOO_MANY_PARAMETERS */
			case ERR_INVALID_ARRAY                 : return 4029; /* ERR_ARRAY_INVALID */
			case ERR_CHART_NO_REPLY                : return 4030; /* ERR_CHART_NOREPLY */

			case ERR_WRONG_INTERNAL_PARAMETER      : return 4052; /* ERR_STRING_FUNCTION_INTERNAL */

			case ERR_SERIES_ARRAY                  : return 4054; /* ERR_INCORRECT_SERIESARRAY_USING */

			case ERR_INCOMPATIBLE_ARRAYS           : return 4056; /* ERR_INCOMPATIBLE_ARRAYS */
			case ERR_GLOBALVARIABLE_EXISTS         :
			case ERR_GLOBALVARIABLE_NOT_MODIFIED   :
			case ERR_GLOBALVARIABLE_CANNOTREAD     :
			case ERR_GLOBALVARIABLE_CANNOTWRITE    : return 4057; /* ERR_GLOBAL_VARIABLES_PROCESSING */
			case ERR_GLOBALVARIABLE_NOT_FOUND      : return 4058; /* ERR_GLOBAL_VARIABLE_NOT_FOUND */

			case ERR_FUNCTION_NOT_ALLOWED          : return 4060; /* ERR_FUNCTION_NOT_CONFIRMED */
			case ERR_MAIL_SEND_FAILED              : return 4061; /* ERR_SEND_MAIL_ERROR */

			case ERR_RESOURCE_NOT_FOUND            : return 4068; /* ERR_RESOURCE_NOT_FOUND */
			case ERR_RESOURCE_UNSUPPOTED_TYPE      : return 4069; /* ERR_RESOURCE_NOT_SUPPORTED */
			case ERR_RESOURCE_NAME_DUPLICATED      : return 4070; /* ERR_RESOURCE_DUPLICATED */
			case ERR_INDICATOR_CANNOT_CREATE       : return 4071; /* ERR_INDICATOR_CANNOT_INIT */
			case ERR_INDICATOR_CANNOT_ADD          :
			case ERR_CHART_INDICATOR_CANNOT_ADD    : return 4072; /* ERR_INDICATOR_CANNOT_LOAD */
			case ERR_HISTORY_NOT_FOUND             : return 4073; /* ERR_NO_HISTORY_DATA */
			case ERR_HISTORY_LOAD_ERRORS           : return 4074; /* ERR_NO_MEMORY_FOR_HISTORY */
			case ERR_BUFFERS_NO_MEMORY             : return 4075; /* ERR_NO_MEMORY_FOR_INDICATOR */
			case ERR_FILE_ENDOFFILE                : return 4099; /* ERR_END_OF_FILE */

			case ERR_TRADE_POSITION_NOT_FOUND      :
			case ERR_TRADE_ORDER_NOT_FOUND         :
			case ERR_TRADE_DEAL_NOT_FOUND          : return 4105; /* ERR_NO_ORDER_SELECTED */
			case ERR_MARKET_UNKNOWN_SYMBOL         :
			case ERR_INDICATOR_UNKNOWN_SYMBOL      : return 4106; /* ERR_UNKNOWN_SYMBOL */

			case ERR_TRADE_DISABLED                :
			case TRADE_RETCODE_CLIENT_DISABLES_AT  : return 4109; /* ERR_TRADE_NOT_ALLOWED */
			case TRADE_RETCODE_SHORT_ONLY          : return 4110; /* ERR_LONGS_NOT_ALLOWED */
			case TRADE_RETCODE_LONG_ONLY           : return 4111; /* ERR_SHORTS_NOT_ALLOWED */
			case TRADE_RETCODE_SERVER_DISABLES_AT  : return 4112; /* ERR_TRADE_EXPERT_DISABLED_BY_SERVER */

			case ERR_OBJECT_WRONG_PROPERTY         : return 4201; /* ERR_UNKNOWN_OBJECT_PROPERTY */
			case ERR_OBJECT_NOT_FOUND              : return 4202; /* ERR_OBJECT_DOES_NOT_EXIST */

			case ERR_OBJECT_ERROR                  : return 4207; /* ERR_SOME_OBJECT_ERROR */
			case ERR_CHART_WRONG_PROPERTY          : return 4210; /* ERR_CHART_PROP_INVALID */
			case ERR_CHART_NOT_FOUND               : return 4211; /* ERR_CHART_NOT_FOUND */
			case ERR_CHART_WINDOW_NOT_FOUND        : return 4212; /* ERR_CHARTWINDOW_NOT_FOUND */
			case ERR_CHART_INDICATOR_NOT_FOUND     : return 4213; /* ERR_CHARTINDICATOR_NOT_FOUND */
			case ERR_MARKET_NOT_SELECTED           : return 4220; /* ERR_SYMBOL_SELECT */
			case ERR_NOTIFICATION_SEND_FAILED      : return 4250; /* ERR_NOTIFICATION_ERROR */
			case ERR_NOTIFICATION_WRONG_PARAMETER  : return 4251; /* ERR_NOTIFICATION_PARAMETER */
			case ERR_NOTIFICATION_WRONG_SETTINGS   : return 4252; /* ERR_NOTIFICATION_SETTINGS */
			case ERR_NOTIFICATION_TOO_FREQUENT     : return 4253; /* ERR_NOTIFICATION_TOO_FREQUENT */
			case ERR_FTP_NOSERVER                  : return 4260; /* ERR_FTP_NOSERVER */
			case ERR_FTP_NOLOGIN                   : return 4261; /* ERR_FTP_NOLOGIN */
			case ERR_FTP_CONNECT_FAILED            : return 4262; /* ERR_FTP_CONNECT_FAILED  */

			case 4524                              : return 4263; /* ERR_FTP_CLOSED */
			case ERR_FTP_CHANGEDIR                 : return 4264; /* ERR_FTP_CHANGEDIR */
			case ERR_FTP_FILE_ERROR                : return 4265; /* ERR_FTP_FILE_ERROR */
			case ERR_FTP_SEND_FAILED               : return 4266; /* ERR_FTP_ERROR */
			case ERR_TOO_MANY_FILES                : return 5001; /* ERR_FILE_TOO_MANY_OPENED */
			case ERR_WRONG_FILENAME                : return 5002; /* ERR_FILE_WRONG_FILENAME */
			case ERR_TOO_LONG_FILENAME             : return 5003; /* ERR_FILE_TOO_LONG_FILENAME */
			case ERR_CANNOT_OPEN_FILE              : return 5004; /* ERR_FILE_CANNOT_OPEN */
			case ERR_FILE_CACHEBUFFER_ERROR        : return 5005; /* ERR_FILE_BUFFER_ALLOCATION_ERROR */
			case ERR_CANNOT_DELETE_FILE            : return 5006; /* ERR_FILE_CANNOT_DELETE */
			case ERR_INVALID_FILEHANDLE            : return 5007; /* ERR_FILE_INVALID_HANDLE */
			case ERR_WRONG_FILEHANDLE              : return 5008; /* ERR_FILE_WRONG_HANDLE */
			case ERR_FILE_NOTTOWRITE               : return 5009; /* ERR_FILE_NOT_TOWRITE */
			case ERR_FILE_NOTTOREAD                : return 5010; /* ERR_FILE_NOT_TOREAD */
			case ERR_FILE_NOTBIN                   : return 5011; /* ERR_FILE_NOT_BIN */
			case ERR_FILE_NOTTXT                   : return 5012; /* ERR_FILE_NOT_TXT */
			case ERR_FILE_NOTTXTORCSV              : return 5013; /* ERR_FILE_NOT_TXTORCSV */
			case ERR_FILE_NOTCSV                   : return 5014; /* ERR_FILE_NOT_CSV */
			case ERR_FILE_READERROR                : return 5015; /* ERR_FILE_READ_ERROR */
			case ERR_FILE_WRITEERROR               : return 5016; /* ERR_FILE_WRITE_ERROR */
			case ERR_FILE_BINSTRINGSIZE            : return 5017; /* ERR_FILE_BIN_STRINGSIZE */
			case ERR_INCOMPATIBLE_FILE             : return 5018; /* ERR_FILE_INCOMPATIBLE */
			case ERR_FILE_IS_DIRECTORY             : return 5019; /* ERR_FILE_IS_DIRECTORY */
			case ERR_FILE_NOT_EXIST                : return 5020; /* ERR_FILE_NOT_EXIST */
			case ERR_FILE_CANNOT_REWRITE           : return 5021; /* ERR_FILE_CANNOT_REWRITE */
			case ERR_WRONG_DIRECTORYNAME           : return 5022; /* ERR_FILE_WRONG_DIRECTORYNAME */
			case ERR_DIRECTORY_NOT_EXIST           : return 5023; /* ERR_FILE_DIRECTORY_NOT_EXIST */
			case ERR_FILE_ISNOT_DIRECTORY          : return 5024; /* ERR_FILE_NOT_DIRECTORY */
			case ERR_CANNOT_DELETE_DIRECTORY       : return 5025; /* ERR_FILE_CANNOT_DELETE_DIRECTORY */
			case ERR_CANNOT_CLEAN_DIRECTORY        : return 5026; /* ERR_FILE_CANNOT_CLEAN_DIRECTORY */
			case ERR_ARRAY_RESIZE_ERROR            : return 5027; /* ERR_FILE_ARRAYRESIZE_ERROR */
			case ERR_STRING_RESIZE_ERROR           : return 5028; /* ERR_FILE_STRINGRESIZE_ERROR */
			case ERR_STRUCT_WITHOBJECTS_ORCLASS    : return 5029; /* ERR_FILE_STRUCT_WITH_OBJECTS */
			case ERR_WEBREQUEST_INVALID_ADDRESS    : return 5200; /* ERR_WEBREQUEST_INVALID_ADDRESS */
			case ERR_WEBREQUEST_CONNECT_FAILED     : return 5201; /* ERR_WEBREQUEST_CONNECT_FAILED */
			case ERR_WEBREQUEST_TIMEOUT            : return 5202; /* ERR_WEBREQUEST_TIMEOUT */
			case ERR_WEBREQUEST_REQUEST_FAILED     : return 5203; /* ERR_WEBREQUEST_REQUEST_FAILED */
			case ERR_USER_ERROR_FIRST              : return 65536; /* ERR_USER_ERROR_FIRST */

			default : return 2; /* ERR_COMMON_ERROR */
		}
	}

	static bool IsTesting() {
		return (bool)::MQLInfoInteger(MQL_TESTER);
	}

	/**
	* Can't find such functionality in MQL5, but I think TERMINAL_CONNECTED should be here
	*/
	static bool IsTradeContextBusy() {
		if (!::TerminalInfoInteger(TERMINAL_CONNECTED)) return true;

		return false;
	}

	static bool IsVisualMode() {
		return (bool)::MQLInfoInteger(MQL_VISUAL_MODE);
	}

	static double MarketInfo(string symbol, int type) {

		if (symbol == NULL) symbol = ::Symbol();

		switch(type) {
			case 1 /* MODE_LOW                */ : return ::SymbolInfoDouble(symbol, SYMBOL_LASTLOW);
			case 2 /* MODE_HIGH               */ : return ::SymbolInfoDouble(symbol, SYMBOL_LASTHIGH);
			case 5 /* MODE_TIME               */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_TIME);
			case 9 /* MODE_BID                */ : return ::SymbolInfoDouble(symbol, SYMBOL_BID);
			case 10 /* MODE_ASK               */ : return ::SymbolInfoDouble(symbol, SYMBOL_ASK);
			case 11 /* MODE_POINT             */ : return ::SymbolInfoDouble(symbol, SYMBOL_POINT);
			case 12 /* MODE_DIGITS            */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_DIGITS);
			case 13 /* MODE_SPREAD            */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_SPREAD);
			case 14 /* MODE_STOPLEVEL         */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL);
			case 15 /* MODE_LOTSIZE           */ : return ::SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
			case 16 /* MODE_TICKVALUE         */ : return ::SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
			case 17 /* MODE_TICKSIZE          */ : return ::SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
			case 18 /* MODE_SWAPLONG          */ : return ::SymbolInfoDouble(symbol, SYMBOL_SWAP_LONG);
			case 19 /* MODE_SWAPSHORT         */ : return ::SymbolInfoDouble(symbol, SYMBOL_SWAP_SHORT);
			case 20 /* MODE_STARTING          */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_START_TIME);
			case 21 /* MODE_EXPIRATION        */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_EXPIRATION_TIME);
			case 22 /* MODE_TRADEALLOWED      */ : return (::SymbolInfoInteger(symbol, SYMBOL_TRADE_MODE) != SYMBOL_TRADE_MODE_DISABLED);
			case 23 /* MODE_MINLOT            */ : return ::SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
			case 24 /* MODE_LOTSTEP           */ : return ::SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
			case 25 /* MODE_MAXLOT            */ : return ::SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
			case 26 /* MODE_SWAPTYPE          */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_SWAP_MODE);
			case 27 /* MODE_PROFITCALCMODE    */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE);
			case 28 /* MODE_MARGINCALCMODE    */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE);
			case 29 /* MODE_MARGININIT        */ : return (double)::SymbolInfoDouble(symbol, SYMBOL_MARGIN_INITIAL);
			case 30 /* MODE_MARGINMAINTENANCE */ : return (double)::SymbolInfoDouble(symbol, SYMBOL_MARGIN_MAINTENANCE);
			case 31 /* MODE_MARGINHEDGED      */ : return (double)::SymbolInfoDouble(symbol, SYMBOL_MARGIN_HEDGED);
			case 32 /* MODE_MARGINREQUIRED    */ :	{

			   double margin = 0.0;

				if (::OrderCalcMargin(ORDER_TYPE_BUY, symbol, 1, ::SymbolInfoDouble(symbol, SYMBOL_ASK), margin))
					return margin;
				else
					return 0.0;
			}
			case 33 /* MODE_FREEZELEVEL */     : return (double)::SymbolInfoInteger(symbol, SYMBOL_TRADE_FREEZE_LEVEL);
			case 34 /* MODE_CLOSEBY_ALLOWED */ : return 0.0;
		}

		return 0.0;
	}

	static bool ObjectCreate(
		long chart_id, string object_name, ENUM_OBJECT object_type, int sub_window,
		datetime time1, double price1,
		datetime time2 = 0, double price2 = 0,
		datetime time3 = 0, double price3 = 0,
		datetime time4 = 0, double price4 = 0,
		datetime time5 = 0, double price5 = 0,
		datetime time6 = 0, double price6 = 0,
		datetime time7 = 0, double price7 = 0,
		datetime time8 = 0, double price8 = 0,
		datetime time9 = 0, double price9 = 0,
		datetime time10 = 0, double price10 = 0,
		datetime time11 = 0, double price11 = 0,
		datetime time12 = 0, double price12 = 0,
		datetime time13 = 0, double price13 = 0,
		datetime time14 = 0, double price14 = 0,
		datetime time15 = 0, double price15 = 0,
		datetime time16 = 0, double price16 = 0,
		datetime time17 = 0, double price17 = 0,
		datetime time18 = 0, double price18 = 0,
		datetime time19 = 0, double price19 = 0,
		datetime time20 = 0, double price20 = 0,
		datetime time21 = 0, double price21 = 0,
		datetime time22 = 0, double price22 = 0,
		datetime time23 = 0, double price23 = 0,
		datetime time24 = 0, double price24 = 0,
		datetime time25 = 0, double price25 = 0,
		datetime time26 = 0, double price26 = 0,
		datetime time27 = 0, double price27 = 0,
		datetime time28 = 0, double price28 = 0,
		datetime time29 = 0, double price29 = 0
	) {
		return (bool)::ObjectCreate(
			chart_id, object_name, object_type, sub_window,
			time1, price1,
			time2, price2,
			time3, price3,
			time4, price4,
			time5, price5,
			time6, price6,
			time7, price7,
			time8, price8,
			time9, price9,
			time10, price10,
			time11, price11,
			time12, price12,
			time13, price13,
			time14, price14,
			time15, price15,
			time16, price16,
			time17, price17,
			time18, price18,
			time19, price19,
			time20, price20,
			time21, price21,
			time22, price22,
			time23, price23,
			time24, price24,
			time25, price25,
			time26, price26,
			time27, price27,
			time28, price28,
			time29, price29
			);
	}

	static bool ObjectCreate(
		string object_name, ENUM_OBJECT object_type, int sub_window,
		datetime time1, double price1,
		datetime time2 = 0, double price2 = 0,
		datetime time3 = 0, double price3 = 0
	) {
		return (bool)::ObjectCreate(0, object_name, object_type, sub_window, time1, price1, time2, price2, time3, price3);
	}

	static bool ObjectDelete(long chart_id, string object_name) {
		return (bool)::ObjectDelete(chart_id, object_name);
	}
	static bool ObjectDelete(string object_name) {
		return (bool)::ObjectDelete(0, object_name);
	}

	/**
	* In MQL5 the names of the constants in ENUM_OBJECT_PROPERTY_* are pretty much the same as in MQL4, so when constants are used the functions below will serve
	*/
	static string ObjectGetString(long chart_id, const string object_name, ENUM_OBJECT_PROPERTY_STRING prop_id, int prop_modifier = 0) {
		return ::ObjectGetString(chart_id, object_name, prop_id, prop_modifier);
	}
	static bool ObjectGetString(long chart_id, const string object_name, ENUM_OBJECT_PROPERTY_STRING prop_id, int prop_modifier, string &string_var) {
		return ::ObjectGetString(chart_id, object_name, prop_id, prop_modifier, string_var);
	}
	/**
	* These overloads are used just in case when integer value is passed to prop_id.
	* It's presumed that this integer value is what represents the enumeration constants in MQL4, which representation is different in MQL5.
	*/
	static string ObjectGetString(long chart_id, const string object_name, int prop_id, int prop_modifier = 0) {
		ENUM_OBJECT_PROPERTY_STRING propID = CCBC::_ConvertEnumObjectPropertyString_(prop_id);
		if (propID == -1) return "";

		return ::ObjectGetString(chart_id, object_name, propID, prop_modifier);
	}
	static bool ObjectGetString(long chart_id, const string object_name, int prop_id, int prop_modifier, string &string_var) {
		ENUM_OBJECT_PROPERTY_STRING propID = CCBC::_ConvertEnumObjectPropertyString_(prop_id);
		if (propID == -1) {
			string_var = "";

			return true;
		}

		return ::ObjectGetString(chart_id, object_name, propID, prop_modifier, string_var);
	}

	/**
	* These overloads are used just in case when integer value is passed to prop_id.
	* It's presumed that this integer value is what represents the enumeration constants in MQL4, which representation is different in MQL5.
	*/
	static bool ObjectSetDouble(long chart_id, const string object_name, ENUM_OBJECT_PROPERTY_DOUBLE prop_id, double prop_value) {
		return ::ObjectSetDouble(chart_id, object_name, prop_id, prop_value);
	}
	static bool ObjectSetDouble(long chart_id, const string object_name, ENUM_OBJECT_PROPERTY_DOUBLE prop_id, int prop_modifier, double prop_value) {
		return ::ObjectSetDouble(chart_id, object_name, prop_id, prop_modifier, prop_value);
	}
	static bool ObjectSetDouble(long chart_id, const string object_name, int prop_id, double prop_value) {
		ENUM_OBJECT_PROPERTY_DOUBLE propID = CCBC::_ConvertEnumObjectPropertyDouble_(prop_id);
		if (propID == -1) return false;

		return ::ObjectSetDouble(chart_id, object_name, propID, prop_value);
	}
	static bool ObjectSetDouble(long chart_id, const string object_name, int prop_id, int prop_modifier, double prop_value) {
		ENUM_OBJECT_PROPERTY_DOUBLE propID = CCBC::_ConvertEnumObjectPropertyDouble_(prop_id);
		if (propID == -1) return false;

		return ::ObjectSetDouble(chart_id, object_name, propID, prop_modifier, prop_value);
	}

	/**
	* These overloads are used just in case when integer value is passed to prop_id.
	* It's presumed that this integer value is what represents the enumeration constants in MQL4, which representation is different in MQL5.
	*/
	static bool ObjectSetInteger(long chart_id, const string object_name, ENUM_OBJECT_PROPERTY_INTEGER prop_id, long prop_value) {
		return ::ObjectSetInteger(chart_id, object_name, prop_id, prop_value);
	}
	static bool ObjectSetInteger(long chart_id, const string object_name, ENUM_OBJECT_PROPERTY_INTEGER prop_id, int prop_modifier, long prop_value) {
		return ::ObjectSetInteger(chart_id, object_name, prop_id, prop_modifier, prop_value);
	}
	static bool ObjectSetInteger(long chart_id, const string object_name, int prop_id, long prop_value) {
		ENUM_OBJECT_PROPERTY_INTEGER propID = CCBC::_ConvertEnumObjectPropertyInteger_(prop_id);
		if (propID == -1) return false;

		return ::ObjectSetInteger(chart_id, object_name, propID, prop_value);
	}
	static bool ObjectSetInteger(long chart_id, const string object_name, int prop_id, int prop_modifier, long prop_value) {
		ENUM_OBJECT_PROPERTY_INTEGER propID = CCBC::_ConvertEnumObjectPropertyInteger_(prop_id);
		if (propID == -1) return false;

		return ::ObjectSetInteger(chart_id, object_name, propID, prop_modifier, prop_value);
	}

	/**
	* These overloads are used just in case when integer value is passed to prop_id.
	* It's presumed that this integer value is what represents the enumeration constants in MQL4, which representation is different in MQL5.
	*/
	static bool ObjectSetString(long chart_id, const string object_name, ENUM_OBJECT_PROPERTY_STRING prop_id, string prop_value) {
		return ::ObjectSetString(chart_id, object_name, prop_id, prop_value);
	}
	static bool ObjectSetString(long chart_id, const string object_name, ENUM_OBJECT_PROPERTY_STRING prop_id, int prop_modifier, string prop_value) {
		return ::ObjectSetString(chart_id, object_name, prop_id, prop_modifier, prop_value);
	}
	static bool ObjectSetString(long chart_id, const string object_name, int prop_id, string prop_value) {
		ENUM_OBJECT_PROPERTY_STRING propID = CCBC::_ConvertEnumObjectPropertyString_(prop_id);
		if (propID == -1) return true;

		return ::ObjectSetString(chart_id, object_name, propID, prop_value);
	}
	static bool ObjectSetString(long chart_id, const string object_name, int prop_id, int prop_modifier, string prop_value) {
		ENUM_OBJECT_PROPERTY_STRING propID = CCBC::_ConvertEnumObjectPropertyString_(prop_id);
		if (propID == -1) return true;

		return ::ObjectSetString(chart_id, object_name, propID, prop_modifier, prop_value);
	}

	static bool OrderClose(long ticket, double lots, double price, int slippage, color arrow_color = clrNONE) {

		int positionsTotal = ::PositionsTotal();
		bool found = false;
		long positionID = ticket;

		for (int index = positionsTotal-1; index >= 0; index--) {
			ticket = (long)::PositionGetTicket(index);
			if (::PositionGetInteger(POSITION_IDENTIFIER) == positionID) {
				found = true;
				break;
			}
		}

		if (!found) {
			if (::HistoryDealSelect(ticket))	{
				long posID = ::HistoryDealGetInteger(ticket, DEAL_POSITION_ID);

				for (int index = positionsTotal-1; index >= 0; index--) {
					ticket = (long)::PositionGetTicket(index);

					if (::PositionGetInteger(POSITION_IDENTIFIER) == posID) {
						found = true;
						break;
					}
				}
			}
		}

		if (!found) return false;

		double lots0   = ::NormalizeDouble(PositionGetDouble(POSITION_VOLUME), 5);
		string symbol  = ::PositionGetString(POSITION_SYMBOL);
		double lotstep = ::SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);

		while (true) {

			lots = ::MathFloor(lots/lotstep)*lotstep;

			MqlTradeRequest request;
			MqlTradeResult result;
			::ZeroMemory(request);
			::ZeroMemory(result);

			request.action    = TRADE_ACTION_DEAL;
			request.price     = price;
			request.type      = (::PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY ;
			request.position  = ::PositionGetInteger(POSITION_TICKET);
			request.symbol    = symbol;
			request.volume    = lots;
			request.magic     = ::PositionGetInteger(POSITION_MAGIC);
			request.deviation = (ulong)slippage;
			request.comment   = "from #" + ::IntegerToString(ticket);

			if (CCBC_TRADES::IsFillingTypeAllowed(symbol, SYMBOL_FILLING_FOK))
				request.type_filling = ORDER_FILLING_FOK;
			else if (CCBC_TRADES::IsFillingTypeAllowed(symbol, SYMBOL_FILLING_IOC))
				request.type_filling = ORDER_FILLING_IOC;
			else if (CCBC_TRADES::IsFillingTypeAllowed(symbol, ORDER_FILLING_RETURN)) // just in case
				request.type_filling = ORDER_FILLING_RETURN;

			int success = ::OrderSend(request, result);

			if (!success || (result.retcode!=TRADE_RETCODE_DONE && result.retcode!=TRADE_RETCODE_PLACED && result.retcode!=TRADE_RETCODE_DONE_PARTIAL)) {
				string errmsgpfx = "Closing trade error";
				int erraction    = CCBC_TRADES::CheckForTradingError(result.retcode, errmsgpfx);

				switch (erraction) {
					case 0: break;    // no error
					case 1: continue; // overcomable error
					case 2: break;    // fatal error
				}
				return false;
			}

			if (result.retcode == TRADE_RETCODE_DONE || result.retcode == TRADE_RETCODE_PLACED || result.retcode == TRADE_RETCODE_DONE_PARTIAL) {

				if (lots0 == ::NormalizeDouble(result.volume, 5)) {
					while (true) {
						if (!::PositionSelectByTicket(ticket)) {
							break;
						}

						::Sleep(10);
					}
				}

				else if (lots0 > ::NormalizeDouble(result.volume, 5))	{
					while (true) {
						if (::PositionSelectByTicket(ticket) && (lots0 != ::NormalizeDouble(PositionGetDouble(POSITION_VOLUME), 5))) {
							break;
						}

						::Sleep(10);
					}
				}
			}

			break;
		}

		::ResetLastError();

		return true;
	}

	static double OrderCommission() {
		if (CCBC_TRADES::LoadedType() == 1) {
			::HistorySelectByPosition(CCBC::OrderTicket());
			int total = ::HistoryDealsTotal();

			for (int index = 0; index < total; index++) {
				ulong ticket = ::HistoryDealGetTicket(index);
				ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)::HistoryDealGetInteger(ticket, DEAL_ENTRY);

				if (entry == DEAL_ENTRY_IN) {
					return ::HistoryDealGetDouble(ticket, DEAL_COMMISSION); 
				}
			}
		}

		if (CCBC_TRADES::LoadedType() == 2) return 0;

		if (CCBC_TRADES::LoadedType() == 3) {
			::HistorySelectByPosition(CCBC::OrderTicket());
			int total = ::HistoryDealsTotal();

			for (int index = total -1; index >= 0; index--) {
				ulong ticket = ::HistoryDealGetTicket(index);
				ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)::HistoryDealGetInteger(ticket, DEAL_ENTRY);

				if (entry == DEAL_ENTRY_OUT) {
					return ::HistoryDealGetDouble(ticket, DEAL_COMMISSION);
				}
			}
		}

		if (CCBC_TRADES::LoadedType() == 4) return 0;

		return 0.0;
	}

	static bool OrderDelete(long ticket, color arrow_color = clrNONE) {
		if (!::OrderSelect(ticket)) return false;

		while (true) {

			MqlTradeRequest request;
			MqlTradeResult result;
			MqlTradeCheckResult check_result;
			::ZeroMemory(request);
			::ZeroMemory(result);
			::ZeroMemory(check_result);

			request.action = TRADE_ACTION_REMOVE;
			request.order  = ticket;

			if (!::OrderCheck(request,check_result)) {
				::Print("OrderCheck() failed: "+(string)check_result.comment+" ("+(string)check_result.retcode+")");

				return false;
			}

			int success = ::OrderSend(request, result);

			if (!success || (result.retcode!=TRADE_RETCODE_DONE && result.retcode!=TRADE_RETCODE_PLACED && result.retcode!=TRADE_RETCODE_DONE_PARTIAL)) {
				string errmsgpfx = "Closing order error";
				int erraction    = CCBC_TRADES::CheckForTradingError(result.retcode, errmsgpfx);

				switch (erraction) {
					case 0: break;    // no error
					case 1: continue; // overcomable error
					case 2: break;    // fatal error
				}

				CCBC::_LastError_(result.retcode);

				return false;
			}

			if (result.retcode==TRADE_RETCODE_DONE || result.retcode==TRADE_RETCODE_PLACED || result.retcode==TRADE_RETCODE_DONE_PARTIAL) {
				while (true) {
					if (!::OrderSelect(ticket)) {
						break;
					}

					::Sleep(10);
				}
			}

			break;
		}

		::ResetLastError();

		return true;
	}

	static double OrderLots() {
		if (CCBC_TRADES::LoadedType() == 1) return ::PositionGetDouble(POSITION_VOLUME);

		if (CCBC_TRADES::LoadedType() == 2) return ::OrderGetDouble(ORDER_VOLUME_CURRENT);

		if (CCBC_TRADES::LoadedType() == 3) {
			::HistorySelectByPosition(CCBC::OrderTicket());
			int total = ::HistoryDealsTotal();

			for (int index = total -1; index >= 0; index--) {
				ulong ticket = ::HistoryDealGetTicket(index);
				ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)::HistoryDealGetInteger(ticket, DEAL_ENTRY);

				if (entry == DEAL_ENTRY_OUT) {
					return ::HistoryDealGetDouble(ticket, DEAL_VOLUME);
				}
			}
		}

		if (CCBC_TRADES::LoadedType() == 4) return ::HistoryOrderGetDouble(CCBC::OrderTicket(), ORDER_VOLUME_CURRENT);

		return 0.0;
	}

	static long OrderMagicNumber() {
		if (CCBC_TRADES::LoadedType() == 1) return (long)::PositionGetInteger(POSITION_MAGIC);

		if (CCBC_TRADES::LoadedType() == 2) return (long)::OrderGetInteger(ORDER_MAGIC);

		if (CCBC_TRADES::LoadedType() == 3) {
			::HistorySelectByPosition(CCBC::OrderTicket());
			int total = ::HistoryDealsTotal();

			for (int index = total -1; index >= 0; index--) {
				ulong ticket = ::HistoryDealGetTicket(index);
				ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)::HistoryDealGetInteger(ticket, DEAL_ENTRY);

				if (entry == DEAL_ENTRY_OUT) {
					return (long)::HistoryDealGetInteger(ticket, DEAL_MAGIC);
				}
			}
		}

		if (CCBC_TRADES::LoadedType() == 4) return (long)::HistoryOrderGetInteger(CCBC::OrderTicket(), ORDER_MAGIC);

		return 0;
	}

	static double OrderOpenPrice() {
		if (CCBC_TRADES::LoadedType() == 1) return ::PositionGetDouble(POSITION_PRICE_OPEN);

		if (CCBC_TRADES::LoadedType() == 2) return ::OrderGetDouble(ORDER_PRICE_OPEN);

		if (CCBC_TRADES::LoadedType() == 3) {
			::HistorySelectByPosition(CCBC::OrderTicket());
			int total = ::HistoryDealsTotal();

			for (int index = 0; index < total; index++) {
				ulong ticket = ::HistoryDealGetTicket(index);
				ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)::HistoryDealGetInteger(ticket, DEAL_ENTRY);

				if (entry == DEAL_ENTRY_IN) {
					return ::HistoryDealGetDouble(ticket, DEAL_PRICE); 
				}
			}
		}

		if (CCBC_TRADES::LoadedType() == 4) return ::HistoryOrderGetDouble(CCBC::OrderTicket(), ORDER_PRICE_OPEN);

		return 0.0;
	}

	static double OrderProfit() {
		if (CCBC_TRADES::LoadedType() == 1) return ::PositionGetDouble(POSITION_PROFIT);

		if (CCBC_TRADES::LoadedType() == 3) {
			::HistorySelectByPosition(CCBC::OrderTicket());
			int total = ::HistoryDealsTotal();

			for (int index = total -1; index >= 0; index--) {
				ulong ticket = ::HistoryDealGetTicket(index);
				ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)::HistoryDealGetInteger(ticket, DEAL_ENTRY);

				if (entry == DEAL_ENTRY_OUT) {
					return ::HistoryDealGetDouble(ticket, DEAL_PROFIT);
				}
			}
		}

		return 0.0;
	}

	static bool OrderSelect(long index, int select, int pool = 0) {

		if (pool < 0 || pool > 1) pool = 0;
		if (select != 0) select = 1;

		bool selected = false;
		int loadedTypeTrade = 1;
		int loadedTypeOrder = 2;

		CCBC::OrderTicket(0);
		CCBC_TRADES::LoadedType(0);

		if (select == 0) {

			int totalTrades = 0;
			int totalOrders = 0;

			if (pool == 1) {
				::HistorySelect(0, ::TimeCurrent() + 1);

				totalTrades = ::HistoryDealsTotal();
				totalOrders = ::HistoryOrdersTotal();

				loadedTypeTrade = 3;
				loadedTypeOrder = 4;
			}
			else {
				totalTrades = ::PositionsTotal();
				totalOrders = ::OrdersTotal();

				loadedTypeTrade = 1;
				loadedTypeOrder = 2;
			}

			if (totalTrades == 0 && totalOrders == 0) {

				CCBC::_LastError_(ERR_INVALID_PARAMETER);
			}
			else {

				int total = ::MathMax(totalTrades, totalOrders);
				int tradeIndex = 0;
				int orderIndex = 0;
				int iterationIndex = 0;

				while (true) {
					ulong tradeTicket = 0;
					ulong orderTicket = 0;

					if (tradeIndex < totalTrades) {

Показано первые 50% кода (символов: 128444)

Открыть по тарифу

Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.

Разовая покупка файла

На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.

Чтобы оформить заказ, введите email и перейдите к оплате.

Стоимость полного кода
12 844,40₽ ≈ $156.98