/*
   Generated by EX4-TO-MQ4 decompiler V4.0.224.1 []
   Website: http://purebeam.biz
   E-mail : purebeam@gmail.com
*/
#property copyright "Copyright © 2007 favoritefx"
#property link      "favoritefx@mail.ru   ICQ 394-005-339"

#import "fa_mt4_interface.dll"
   bool InitExpert(string a0, string a1, int a2, double a3, double a4);
   bool DeinitExpert(string a0);
   bool GetAction(string a0, double a1, double a2, int& a3[], int& a4[], double& a5[]);
   bool ReturnResult(string a0, int a1, int a2, double a3, int a4, double a5, int a6);
   void InSync();
#import

int g_slippage_76 = 3;
int gi_80 = 300;
int gi_84 = 280;
int gi_88 = 10;
int gi_92 = 5;
bool gi_96 = FALSE;
string gs_100;
bool gi_108 = FALSE;
int gi_112 = 5;
bool gi_unused_116 = FALSE;
bool gi_120 = FALSE;
int gi_124 = 10;
int gi_128 = 10;

string SymbolName() {
   string ls_unused_0;
   int li_8 = StringFind(Symbol(), "mini", 0);
   if (li_8 != -1) return (StringSubstr(Symbol(), 0, li_8));
   li_8 = StringFind(Symbol(), "!", 0);
   if (li_8 != -1) return (StringSubstr(Symbol(), 0, li_8));
   return (Symbol());
}

double TickValue(string a_symbol_0, int ai_8) {
   string l_symbol_28;
   double ld_ret_12 = MarketInfo(a_symbol_0, MODE_TICKVALUE);
   if (StringLen(a_symbol_0) != 6) return (ld_ret_12);
   double ld_20 = MarketInfo(a_symbol_0, MODE_LOTSIZE) * MarketInfo(a_symbol_0, MODE_TICKSIZE);
   if (StringSubstr(a_symbol_0, 3, 3) == "USD") return (ld_ret_12);
   if (StringSubstr(a_symbol_0, 0, 3) == "USD") ld_ret_12 = ld_20 / iClose(a_symbol_0, 0, ai_8);
   else {
      l_symbol_28 = StringSubstr(a_symbol_0, 0, 3) + "USD";
      if (iClose(l_symbol_28, 0, 0) == 0.0) l_symbol_28 = "USD" + StringSubstr(a_symbol_0, 0, 3);
      if (iClose(l_symbol_28, 0, 0) == 0.0) return (ld_ret_12);
      if (StringSubstr(l_symbol_28, 0, 3) == "USD") ld_ret_12 = ld_20 / iClose(l_symbol_28, 0, ai_8) / iClose(a_symbol_0, 0, ai_8);
      else ld_ret_12 = ld_20 * iClose(l_symbol_28, 0, ai_8) / iClose(a_symbol_0, 0, ai_8);
   }
   return (ld_ret_12);
}

int CloseOrder(int a_magic_0, int ai_4) {
   int l_ticket_8;
   double l_price_12;
   int li_20;
   int li_28;
   int l_count_24 = 0;
   for (int l_pos_32 = OrdersTotal() - 1; l_pos_32 >= 0; l_pos_32--) {
      if (OrderSelect(l_pos_32, SELECT_BY_POS, MODE_TRADES)) {
         if (OrderSymbol() == Symbol()) {
            if (OrderMagicNumber() == a_magic_0) {
               l_ticket_8 = OrderTicket();
               li_28 = TimeCurrent();
               while (l_count_24 < gi_88) {
                  l_count_24++;
                  if (OrderType() == OP_BUY) l_price_12 = NormalizeDouble(Bid, Digits);
                  if (OrderType() == OP_SELL) l_price_12 = NormalizeDouble(Ask, Digits);
                  if (OrderClose(OrderTicket(), OrderLots(), l_price_12, g_slippage_76)) {
                     li_28 = TimeCurrent() - li_28;
                     if (OrderSelect(l_ticket_8, SELECT_BY_TICKET) == TRUE) {
                        if (!ReturnResult(gs_100, a_magic_0, ai_4, OrderClosePrice(), 1, AccountFreeMargin(), li_28)) Print("Error to data ");
                        Print("Закрылась на " + l_count_24 + " попытке");
                        return (1);
                     }
                  }
                  li_20 = ErrorBlock();
                  if (li_20 == 3) {
                     Print("СДЕЛКА НЕ ЗАКРЫЛАСЬ, возникла критическая ошибка");
                     ReturnResult(gs_100, a_magic_0, ai_4, 0, 0, AccountFreeMargin(), 0);
                     return (0);
                  }
                  Sleep(5000);
                  RefreshRates();
               }
               Print("СДЕЛКА НЕ ЗАКРЫЛАСЬ за необходимое количество попыток");
               ReturnResult(gs_100, a_magic_0, ai_4, 0, 0, AccountFreeMargin(), 0);
               return (0);
            }
         }
      }
   }
   if (gi_96) {
      ReturnResult(gs_100, a_magic_0, ai_4, 0, 1, AccountFreeMargin(), 0);
      return (1);
   }
   return (0);
}

int Deal(int ai_0, double ad_4, int a_magic_12) {
   int l_ticket_20;
   int li_24;
   double l_price_28;
   int l_cmd_44;
   double l_price_48;
   double l_price_56;
   int l_count_16 = 0;
   double ld_64 = 0;
   double l_lots_36 = NormalizeDouble(ad_4, 1);
   if (ai_0 == 1) ld_64 = NormalizeDouble(Ask, Digits);
   if (ai_0 == 2) ld_64 = NormalizeDouble(Bid, Digits);
   int li_72 = TimeCurrent();
   while (l_count_16 < gi_92) {
      l_count_16++;
      if (ai_0 == 1) {
         l_price_28 = NormalizeDouble(Ask, Digits);
         l_price_48 = NormalizeDouble(l_price_28 + gi_84 * Point, Digits);
         l_price_56 = NormalizeDouble(l_price_28 - gi_80 * Point, Digits);
         l_cmd_44 = 0;
      }
      if (ai_0 == 2) {
         l_price_28 = NormalizeDouble(Bid, Digits);
         l_price_48 = NormalizeDouble(l_price_28 - gi_84 * Point, Digits);
         l_price_56 = NormalizeDouble(l_price_28 + gi_80 * Point, Digits);
         l_cmd_44 = 1;
      }
      l_ticket_20 = OrderSend(Symbol(), l_cmd_44, l_lots_36, l_price_28, g_slippage_76, l_price_56, l_price_48, 0, a_magic_12);
      if (l_ticket_20 > 0) {
         li_72 = TimeCurrent() - li_72;
         if (OrderSelect(l_ticket_20, SELECT_BY_TICKET) == TRUE) {
            if (!ReturnResult(gs_100, a_magic_12, ai_0, OrderOpenPrice(), 1, AccountFreeMargin(), li_72)) {
               Print("Error to data ");
               return (0);
            }
         } else {
            Print("OrderSelect() вернул ошибку - ", GetLastError());
            return (0);
         }
         Print("Открылась на " + l_count_16 + " попытке");
         return (l_ticket_20);
      }
      li_24 = ErrorBlock();
      if (li_24 > 1) {
         Print("СДЕЛКА НЕ ОТКРЫЛАСЬ из-за ошибки");
         ReturnResult(gs_100, a_magic_12, ai_0, 0, 0, AccountFreeMargin(), 0);
         return (0);
      }
      Sleep(5000);
      RefreshRates();
   }
   ReturnResult(gs_100, a_magic_12, ai_0, 0, 0, AccountFreeMargin(), 0);
   Print("СДЕЛКА НЕ ОТКРЫЛАСЬ за необходимое количество попыток");
   return (0);
}

int ErrorBlock() {
   bool l_bool_8;
   int l_count_12;
   int l_error_0 = GetLastError();
   switch (l_error_0) {
   case 0/* NO_ERROR */:
      return (0);
   case 2/* COMMON_ERROR */:
      Print("Сбой системы. Перезагрузить компьютер/проверить сервер");
      return (3);
   case 3/* INVALID_TRADE_PARAMETERS */:
      Print("Ошибка в логике эксперта");
      return (3);
   case 4/* SERVER_BUSY */:
      Print("Торговый сервер занят. Ждем 2 минуты");
      Sleep(120000);
      return (2);
   case 6/* NO_CONNECTION */:
      l_bool_8 = FALSE;
      l_count_12 = 0;
      Print("Disconnect");
      while (!l_bool_8) {
         Sleep(5000);
         Print("Связь не восстановлена, прошло ", 5 * l_count_12, "  секунд");
         l_count_12++;
         l_bool_8 = IsConnected();
         if (l_bool_8) {
            Print("Связь восстановлена");
            return (0);
         }
      }
   case 8/* TOO_FREQUENT_REQUESTS */:
      Print("Частые запросы");
      return (3);
   case 64/* ACCOUNT_DISABLED */:
      Print("Счет заблокирован!!!");
      return (3);
   case 65/* INVALID_ACCOUNT */:
      Print("Неправильный номер счета???");
      return (3);
   case 128/* TRADE_TIMEOUT */:
      Print("Истек срок ожидания сделки");
      return (2);
   case 129/* INVALID_PRICE */:
      Print("Неверная цена");
      return (1);
   case 130/* INVALID_STOPS */:
      Print("Неверный стоп");
      return (1);
   case 131/* INVALID_TRADE_VOLUME */:
      Print("Неверно расситывается объем сделки");
      return (3);
   case 132/* MARKET_CLOSED */:
      Print("Рынок закрыт");
      Sleep(120000);
      return (2);
   case 134/* NOT_ENOUGH_MONEY */:
      Print("Не хватает маржи для проведения операции");
      return (2);
   case 135/* PRICE_CHANGED */:
      Print("Цены изменились");
      return (1);
   case 136/* OFF_QUOTES */:
      Print("Цен нет!");
      return (2);
   case 138/* REQUOTE */:
      Print("Реквот, снова!");
      return (1);
   case 139/* ORDER_LOCKED */:
      Print("Ордер в обработке. Глюк программы");
      return (2);
   case 141/* TOO_MANY_REQUESTS */:
      Print("Слишком много запросов");
      return (2);
   case 146/* TRADE_CONTEXT_BUSY */:
      Print("Семафоры арбитра не работают!");
      return (1);
   case 148/* ERR_TRADE_TOO_MANY_ORDERS */:
      Print("Слишком много лотов");
      return (2);
   }
   return (0);
}

int init() {
   gs_100 = SymbolName();
   if (IsDllsAllowed() == FALSE) {
      Print("Вызов из библиотек (DLL) невозможен. Эксперт не может выполняться.");
      return (0);
   }
   if (!IsTradeAllowed()) {
      Print("Торговля  не разрешена!");
      return (0);
   }
   int l_digits_0 = MarketInfo(Symbol(), MODE_DIGITS);
   double ld_4 = TickValue(gs_100, 1);
   if (l_digits_0 > 0 || Bid > 0.0) {
      if (!InitExpert(AccountServer(), gs_100, l_digits_0, AccountFreeMargin(), ld_4)) {
         Print("Не удалось создать нового брокера");
         return (0);
      }
      gi_108 = TRUE;
      Print("Брокер успешно создан ");
      return (0);
   }
   Print("Символа нет в MarketInfo!");
   return (0);
}

int deinit() {
   for (int li_0 = OrdersTotal() - 1; li_0 >= 0; li_0--) {
      if (OrderSymbol() == Symbol()) {
         if (OrderType() == OP_BUY) OrderClose(OrderTicket(), OrderLots(), NormalizeDouble(Bid, Digits), 10);
         if (OrderType() == OP_SELL) OrderClose(OrderTicket(), OrderLots(), NormalizeDouble(Ask, Digits), 10);
      }
   }
   if (!DeinitExpert(gs_100)) {
      Print("Брокер не удаляется");
      return (0);
   }
   Print("Брокер успешно удален");
   return (0);
}

int start() {
   int lia_0[1] = {0};
   double lda_4[1] = {1};
   int lia_8[1] = {0};
   double l_bid_16 = Bid;
   int li_unused_24 = 0;
   int l_datetime_28 = 0;
   int li_unused_32 = 1;
   if (!gi_108) return (0);
   while (true) {
      gi_96 = FALSE;
      RefreshRates();
      InSync();
      if (gi_120) {
         Sleep(1000);
         if (TimeCurrent() - l_datetime_28 > gi_128) {
            l_datetime_28 = 0;
            gi_120 = FALSE;
         }
      } else {
         GetAction(gs_100, Bid, Ask, lia_8, lia_0, lda_4);
         if (lia_0[0] == 1 || lia_0[0] == 2) {
            if (MathAbs(Bid - l_bid_16) > gi_124 * Point) {
               Print("Выброс на " + ((Bid - l_bid_16) / Point) + " пунктов");
               gi_120 = TRUE;
               l_datetime_28 = TimeCurrent();
               ReturnResult(gs_100, lia_8[0], lia_0[0], 0, 0, AccountFreeMargin(), 0);
            } else {
               Deal(lia_0[0], lda_4[0], lia_8[0]);
               Sleep(1000 * gi_112);
            }
         }
         if (lia_0[0] == 3) {
            CloseOrder(lia_8[0], lia_0[0]);
            Sleep(1000 * gi_112);
         }
         if (lia_0[0] == 5) {
            gi_96 = TRUE;
            CloseOrder(lia_8[0], lia_0[0]);
            Sleep(1000 * gi_112);
         }
      }
      if (MathAbs(Bid - l_bid_16) > gi_124 * Point) {
         Print("Выброс на " + ((Bid - l_bid_16) / Point) + " пунктов");
         gi_120 = TRUE;
         l_datetime_28 = TimeCurrent();
      }
      l_bid_16 = Bid;
      lia_0[0] = 0;
      lia_8[0] = 0;
   }
   return /*(WARN)*/;
}
