/*
   Generated by EX4-TO-MQ4 decompiler V4.0.224.1 []
   Website: http://purebeam.biz
   E-mail : purebeam@gmail.com
*/
#property copyright "Dominic R. Millan"
#property link      "www.fxirobot.com"

#include <stdlib.mqh>

extern string EA_Comment = "";
extern double Order_Size = 0.1;
extern int Order_Count = 1;
extern int Satefy_Margin = 0;
extern int Exit_Gap = 2;
extern bool closeOrderWhenSamePrice = FALSE;
extern double trailingStopLoss = 2.0;
extern int closeOrderDelay = 0;
extern double Risk_Management = 10.0;
extern bool Trade_OnHalfHour = FALSE;
extern bool pendingOrders = TRUE;
extern bool Use_ECN = TRUE;
extern int takeProfitPoints = 500;
extern int Extra_StopLoss = 0;
string gs_332 = "ManiaeslowPC0FXvv";
double gd_340 = 1.0;
bool gi_348 = FALSE;
bool gi_352 = FALSE;
double gd_356 = 10.0;
double gd_364 = 0.0;
bool gi_372 = FALSE;
int gi_376 = 1;
string g_symbol_380 = "";
string gs_388 = "";
double gd_396 = -1.0;
int gi_404 = 110999;
int gi_408 = 0;
int gi_412 = -1;
double gd_416;
double gd_424;
double gd_432 = 1.0;
string gs_440 = "MetaTrader (MASTER)\\experts\\files";

int init() {
   double ld_8;
   int l_file_60;
   double ld_64;
   int lia_112[20];
   int lia_116[20];
   int li_unused_124;
   int li_unused_128;
   double ld_132;
   int li_140;
   string ls_144;
   string ls_152;
   double l_str2dbl_160;
   double ld_168;
   double ld_176;
   int li_184;
   int li_188;
   int li_192;
   int li_208;
   double ld_212;

   gd_356 = (1 - Risk_Management / 100.0) * AccountBalance();
   gi_404 = 0;
   for (int l_str_len_0 = StringLen(gs_332); l_str_len_0 > 0; l_str_len_0--) 
      gi_404 += StringGetChar(gs_332, l_str_len_0);
   
   g_symbol_380 = Symbol();
   Print("started: currencyPair=" + g_symbol_380);
   int li_4 = TimeLocal();
   li_4 -= 18000;
   double l_stoplevel_16 = MarketInfo(g_symbol_380, MODE_STOPLEVEL);
   gd_396 = l_stoplevel_16 + Extra_StopLoss;
   double l_point_24 = MarketInfo(g_symbol_380, MODE_POINT);
   double ld_32 = (Satefy_Margin + 2.0 * ld_8) * l_point_24;
   string ls_40 = "";
   ls_40 = "";
   ls_40 = "" + TimeYear(li_4);
   ls_40 = ls_40 + "-" + TimeMonth(li_4);
   ls_40 = ls_40 + "-" + TimeDay(li_4);
   string l_name_48 = gs_440 + "\\" + "log_mania_server_expert_" + StringSubstr(g_symbol_380, 0, 6) + "_" + ls_40 + ".csv";
   int li_56 = -1;
   gd_416 = MarketInfo(Symbol(), MODE_ASK);
   gd_424 = MarketInfo(Symbol(), MODE_BID);
   double ld_72 = gd_424 + (gd_416 - gd_424) / 2.0;
   double ld_80 = -1;
   int li_88 = -1;
   double ld_92 = -1;
   int li_100 = 0;
   string ls_unused_104 = "";
   bool li_120 = FALSE;
   if (MarketInfo("GBPUSD", MODE_POINT) < 0.00009) li_120 = TRUE;
   while (true) {
      if (gd_416 != MarketInfo(Symbol(), MODE_ASK) + gd_364 * l_point_24) {
         gd_416 = MarketInfo(Symbol(), MODE_ASK) + gd_364 * l_point_24;
         gd_424 = MarketInfo(Symbol(), MODE_BID) + gd_364 * l_point_24;
         gi_408++;
      }
      li_4 = TimeLocal();
      li_4 -= 18000;
      ls_40 = "";
      ls_40 = "" + TimeYear(li_4);
      ls_40 = ls_40 + "-" + TimeMonth(li_4);
      ls_40 = ls_40 + "-" + TimeDay(li_4);
      l_name_48 = gs_440 + "\\" + "log_mania_server_expert_" + StringSubstr(g_symbol_380, 0, 6) + "_" + ls_40 + ".csv";
      ld_8 = MathRound((MarketInfo(g_symbol_380, MODE_ASK) - MarketInfo(g_symbol_380, MODE_BID)) / l_point_24);
      li_unused_124 = MathRound((MarketInfo(g_symbol_380, MODE_ASK) - MarketInfo(g_symbol_380, MODE_BID)) / l_point_24);
      li_unused_128 = MarketInfo(g_symbol_380, MODE_SPREAD);
      ld_32 = (Satefy_Margin + 2.0 * ld_8) * l_point_24;
      ld_132 = gi_376 * l_point_24;
      l_file_60 = FileOpen(l_name_48, FILE_CSV|FILE_READ);
      if (l_file_60 == -1) {
         Sleep(10);
         continue;
      }
      if (li_56 != FileSize(l_file_60) || gi_408 != gi_412) {
         if (li_56 != FileSize(l_file_60)) {
            li_140 = FileSize(l_file_60);
            if (li_56 != -1) {
               gi_412 = gi_408;
               ld_64 = gd_424 + (gd_416 - gd_424) / 2.0;
               if (li_120) ld_64 = 10.0 * MathRound(ld_64 / l_point_24 / 10.0) * l_point_24;
               FileSeek(l_file_60, li_56, SEEK_SET);
               ls_144 = FileReadString(l_file_60, li_140 - li_56);
               ls_152 = FileReadString(l_file_60, li_140 - li_56);
               l_str2dbl_160 = StrToDouble(ls_152);
               if (l_str2dbl_160 == 0.0) {
                  Print("no price");
                  FileClose(l_file_60);
                  continue;
               }
            }
            ld_168 = MathAbs(ld_64 - l_str2dbl_160);
            ld_176 = MathAbs(ld_72 - ld_64);
            li_184 = (ld_64 - l_str2dbl_160) / l_point_24;
            if (li_120) li_184 = MathRound(li_184 / 10);
            li_184 += 10;
            li_188 = ld_8;
            lia_116[li_188]++;
            if (li_184 < ArraySize(lia_112) && li_184 >= 0) lia_112[li_184]++;
            li_192 = 0;
            for (int l_index_196 = 0; l_index_196 < ArraySize(lia_112); l_index_196++)
               if (lia_112[l_index_196] > lia_112[li_192]) li_192 = l_index_196;
 //           Print("Market Analysis in Progress");
            if (gi_352 == TRUE) {
               Print("l=" + ((l_str2dbl_160 - ld_64)) + ", m=" + l_str2dbl_160 + ", s=" + ld_64 + ", mil=" + ld_32 + ", mol=" + ((li_192 - 10)) + ", cml=" + lia_112[li_192] + ", lp=" +
                  ((li_184 - 10)) + ", ed=" + li_120 + ",cl:," + gd_364);
            }
            if (ld_168 > ld_132 || gd_432 > ld_132) {
               log(",masterPrice:," + l_str2dbl_160 + ",slaveMarketPrice:," + ld_64 + ",lag:," + ((ld_64 - l_str2dbl_160)) + ",slaveJump:," + ld_176 + ",spread:," + ld_8 + ",comment:," +
                  EA_Comment + ",cl:," + gd_364);
            }
            gd_432 = ld_168;
            if (li_184 - ArraySize(lia_112) / 2 > 9 || li_184 - ArraySize(lia_112) / 2 < -9) {
               gi_372 = FALSE;
               gd_364 = 0;
               for (int l_index_200 = 0; l_index_200 < ArraySize(lia_112); l_index_200++) lia_112[l_index_200] = 0;
            }
            if ((lia_112[li_192] > 10 && gi_372 == FALSE) || lia_112[li_192] > 20) {
               gd_364 -= li_192 - 10;
               gi_372 = TRUE;
               for (int l_index_204 = 0; l_index_204 < ArraySize(lia_112); l_index_204++) lia_112[l_index_204] = 0;
            }
            if (ld_168 >= ld_32 && ld_176 == 0.0 && ld_80 == -1.0 && gi_372 && isOnHalfHour() == 1 || Trade_OnHalfHour == FALSE) {
               log(",PlaceOrder:," + l_str2dbl_160 + ",slaveMarketPrice:," + ld_64 + ",lag:," + ((ld_64 - l_str2dbl_160)) + ",slave market ask:," + MarketInfo(Symbol(), MODE_ASK) +
                  ",slave market bid:," + MarketInfo(Symbol(), MODE_BID) + ",comment:," + EA_Comment);
               if (gi_352 == TRUE) Print(",PlaceOrder:," + l_str2dbl_160 + ",slaveMarketPrice:," + ld_64 + ",lag:," + ((ld_64 - l_str2dbl_160)) + ",O" + ",comment:," + EA_Comment);
               ld_92 = gd_416;
               ld_64 = gd_424 + (gd_416 - gd_424) / 2.0;
               li_100 = 0;
               while (l_str2dbl_160 > ld_64 && ld_168 > ld_32 && li_100 < 1) {
                  log(",,,spreadNow=" + MarketInfo(g_symbol_380, MODE_SPREAD) + ",spreadWas=" + ld_8 + ",askPrice=" + gd_416 + ",lagSizeOffsetPoints=" + gd_364 + ",stopsLevel=" + MarketInfo(g_symbol_380, MODE_STOPLEVEL) +
                     ",point=" + l_point_24);
                  if (pendingOrders) {
                     ld_92 = gd_416 - gd_364 * l_point_24 + (l_stoplevel_16 + ld_8) * l_point_24;
                     li_208 = 4;
                     ld_212 = ld_92 - (gd_396 + ld_8) * l_point_24;
                  } else {
                     ld_92 = gd_416 - gd_364 * l_point_24;
                     li_208 = 0;
                     ld_212 = ld_92 - gd_396 * l_point_24;
                  }
                  if (gi_348) Order_Size = getMaxOrder_Size(li_208);
                  li_100 = sendOrder(g_symbol_380, li_208, Order_Size, ld_92, ld_212, ld_92 + takeProfitPoints * l_point_24, li_100);
                  if (li_100 == 0) {
                     for (int li_220 = 1; li_220 < Order_Count; li_220++) sendOrder(g_symbol_380, li_208, Order_Size, ld_92, ld_212, ld_92 + takeProfitPoints * l_point_24, li_100);
                     ld_80 = ld_92;
                     li_88 = li_208;
                     break;
                  }
                  ld_64 = gd_424 + (gd_416 - gd_424) / 2.0;
                  ld_168 = MathAbs(ld_64 - l_str2dbl_160);
               }
               ld_92 = gd_424;
               ld_64 = gd_424 + (gd_416 - gd_424) / 2.0;
               li_100 = 0;
               while (l_str2dbl_160 < ld_64 && ld_168 > ld_32 && li_100 < 1) {
                  log(",,,,spreadNow=" + MarketInfo(g_symbol_380, MODE_SPREAD) + ",spreadWas=" + ld_8 + ",bidPrice=" + gd_424 + ",lagSizeOffsetPoints=" + gd_364 + ",stopsLevel=" + l_stoplevel_16 +
                     ",point=" + l_point_24);
                  if (pendingOrders) {
                     ld_92 = gd_424 - gd_364 * l_point_24 - (l_stoplevel_16 + ld_8) * l_point_24;
                     li_208 = 5;
                     ld_212 = ld_92 + (gd_396 + ld_8) * l_point_24;
                  } else {
                     ld_92 = gd_424 - gd_364 * l_point_24;
                     li_208 = 1;
                     ld_212 = ld_92 + gd_396 * l_point_24;
                  }
                  if (gi_348) Order_Size = getMaxOrder_Size(li_208);
                  li_100 = sendOrder(g_symbol_380, li_208, Order_Size, ld_92, ld_212, ld_92 - takeProfitPoints * l_point_24, li_100);
                  if (li_100 == 0) {
                     for (int li_224 = 1; li_224 < Order_Count; li_224++) sendOrder(g_symbol_380, li_208, Order_Size, ld_92, ld_212, ld_92 - takeProfitPoints * l_point_24, li_100);
                     ld_80 = ld_92;
                     li_88 = li_208;
                     break;
                  }
                  ld_64 = gd_424 + (gd_416 - gd_424) / 2.0;
                  ld_168 = MathAbs(ld_64 - l_str2dbl_160);
               }
               if (ld_80 != -1.0) Print("Placed: orderOpenPrice=" + ld_80);
            }
            if (ld_80 != -1.0) {
               if ((l_str2dbl_160 - ld_64 <= l_point_24 * Exit_Gap && li_88 == 0 || li_88 == 4) || 
                  (ld_64 - l_str2dbl_160 <= l_point_24 * Exit_Gap && li_88 == 1 || li_88 == 5) ||
                  (ld_80 - ld_64 > l_point_24 * trailingStopLoss && li_88 == 0 || li_88 == 4) || 
                  (ld_64 - ld_80 > l_point_24 * trailingStopLoss && li_88 == 1 || li_88 == 5)) {
                  log(",CloseOrderRequest:," + l_str2dbl_160 + ",slaveMarketPrice:," + ld_64 + ",lag:," + ((ld_64 - l_str2dbl_160)) + ",comment:," + EA_Comment);
                  Sleep(1000 * closeOrderDelay);
                  if (closeOrderWhenSamePrice) {
                     for (int li_228 = 600; li_228 != 0; li_228--) {
                        if (closeOpenOrdersAndPending(g_symbol_380, encript(gi_404)) == 1) break;
                        Sleep(100);
                     }
                  }
                  ld_80 = -1;
               }
            }
            updateTrailingStop(g_symbol_380, encript(gi_404), gd_396);
            if (ld_64 != ld_72) ld_72 = ld_64;
         }
         li_56 = li_140;
      }
      FileClose(l_file_60);
      Sleep(100);
   }
   return /*(WARN)*/;
}

int deinit() {
   return (0);
}

int start() {
   return (0);
}

int encript(int ai_0) {
   for (int l_str_len_4 = StringLen(gs_332); l_str_len_4 > 0; l_str_len_4--) ai_0 += StringGetChar(gs_332, l_str_len_4);
   return (ai_0);
}

int closeOpenOrdersAndPending(string as_0, int a_magic_8) {
   int li_12;
   int l_cmd_20;
   double l_price_32;
   int l_error_40;
   bool li_ret_16 = TRUE;
   int l_ord_total_24 = OrdersTotal();
   for (int l_pos_28 = l_ord_total_24 - 1; l_pos_28 >= 0; l_pos_28--) {
      if (OrderSelect(l_pos_28, SELECT_BY_POS, MODE_TRADES)) {
         l_cmd_20 = OrderType();
         if (l_cmd_20 == OP_BUY || l_cmd_20 == OP_SELL) {
            OrderPrint();
            if (OrderMagicNumber() == a_magic_8 && StringFind(OrderSymbol(), as_0, 0) != -1) {
               while (true) {
                  if (OrderType() == OP_BUY) l_price_32 = MarketInfo(as_0, MODE_BID);
                  else l_price_32 = MarketInfo(as_0, MODE_ASK);
                  li_12 = OrderClose(OrderTicket(), OrderLots(), l_price_32, 3, CLR_NONE);
                  if (li_12 != 1) {
                     l_error_40 = GetLastError();
                     Print("Error = ", ErrorDescription(l_error_40), " code=", l_error_40);
                     log("Close error," + l_error_40 + ",price=," + l_price_32 + ",currencyPair=," + as_0);
                     li_ret_16 = FALSE;
                  } else l_error_40 = 0;
                  if (l_error_40 != 135/* PRICE_CHANGED */) break;
                  RefreshRates();
               }
            }
         }
         if (l_cmd_20 != OP_BUY && l_cmd_20 != OP_SELL) {
            OrderPrint();
            li_12 = OrderDelete(OrderTicket());
            if (li_12 != 1) Print("LastError = ", GetLastError());
         }
      } else {
         Print("Error when order select ", GetLastError());
         break;
      }
   }
   return (li_ret_16);
}

int sendOrder(string a_symbol_0, int a_cmd_8, double a_lots_12, double a_price_20, double a_price_28, double a_price_36, int ai_44) {
   int l_error_60;
   if (AccountBalance() < gd_356) return (ai_44 + 10);
   double l_point_48 = MarketInfo(a_symbol_0, MODE_POINT);
   int l_slippage_64 = 0;
   double l_price_68 = a_price_28;
   double l_price_76 = a_price_36;
   if (Use_ECN) a_price_28 = 0;
   if (Use_ECN) a_price_36 = 0;
   int l_ticket_56 = OrderSend(a_symbol_0, a_cmd_8, a_lots_12, a_price_20, l_slippage_64, a_price_28, a_price_36, EA_Comment, encript(gi_404), 0, Green);
   log("send order" + ",currencyPair=" + a_symbol_0 + ",command=" + getOrderTypeName(a_cmd_8) + ",Order_Size=" + a_lots_12 + ",currencyPrice=" + a_price_20 + ",stopLoss=" +
      a_price_28 + ",takeProfit=" + 0 + ",magicNumber=" + gi_404 + ",comment:," + EA_Comment + ",ticket:," + l_ticket_56);
   if (l_ticket_56 <= 0) {
      l_error_60 = GetLastError();
      log("Error:send order" + ",error code=" + l_error_60);
      Print(" --**-- send order error :", ErrorDescription(l_error_60), " code=", l_error_60);
      return (ai_44 + 1);
   }
   if (Use_ECN) addStopLossTakeProfit(l_ticket_56, l_price_68, l_price_76);
   return (0);
}

string getOrderTypeName(int ai_0) {
   string ls_ret_4 = "?" + ai_0 + "?";
   switch (ai_0) {
   case 0:
      ls_ret_4 = "OP_BUY";
      break;
   case 4:
      ls_ret_4 = "OP_BUYSTOP";
      break;
   case 1:
      ls_ret_4 = "OP_SELL";
      break;
   case 5:
      ls_ret_4 = "OP_SELLSTOP";
   }
   return (ls_ret_4);
}

void addStopLossTakeProfit(int a_ticket_0, double a_price_4, double a_price_12) {
   OrderSelect(a_ticket_0, SELECT_BY_TICKET);
   bool l_bool_20 = FALSE;
   for (int l_count_24 = 0; l_count_24 < 5 && l_bool_20 == FALSE; l_count_24++) {
      l_bool_20 = OrderModify(OrderTicket(), OrderOpenPrice(), a_price_4, a_price_12, 0, Blue);
      if (l_bool_20 == FALSE) Sleep(300);
   }
}

double getFreeMarginInBaseCurrency() {
   double l_free_magrin_0 = AccountFreeMargin();
   return (convertToBaseCurrency(l_free_magrin_0));
}

double convertToBaseCurrency(double ad_0) {
   string ls_8 = StringSubstr(g_symbol_380, 3, 3);
   if (StringFind(AccountCurrency(), ls_8, 0) == -1) {
      if (MarketInfo(ls_8 + AccountCurrency() + gs_388, MODE_ASK) != 0.0) ad_0 /= MarketInfo(ls_8 + AccountCurrency() + gs_388, MODE_ASK);
      else ad_0 /= 1 / MarketInfo(AccountCurrency() + ls_8 + gs_388, MODE_ASK);
   }
   return (ad_0);
}

bool isFixedMaxOrder_Size() {
   if (MarketInfo("AUDUSD" + gs_388, MODE_MARGINREQUIRED) == MarketInfo("USDJPY" + gs_388, MODE_MARGINREQUIRED) && MarketInfo("AUDUSD" + gs_388, MODE_MARGINREQUIRED) == MarketInfo("EURUSD" +
      gs_388, MODE_MARGINREQUIRED)) return (TRUE);
   return (FALSE);
}

double getMaxOrder_Size(int ai_0) {
   double ld_16;
   if (StringLen(g_symbol_380) == 7) gs_388 = ".";
   int l_stoplevel_4 = MarketInfo(g_symbol_380, MODE_STOPLEVEL);
   double l_point_8 = MarketInfo(g_symbol_380, MODE_POINT);
   if (ai_0 == 4) ld_16 = MarketInfo(g_symbol_380, MODE_ASK) + l_stoplevel_4 * l_point_8;
   if (ai_0 == 5) ld_16 = MarketInfo(g_symbol_380, MODE_BID) - l_stoplevel_4 * l_point_8;
   if (ai_0 == 0) ld_16 = MarketInfo(g_symbol_380, MODE_ASK);
   if (ai_0 == 1) ld_16 = MarketInfo(g_symbol_380, MODE_BID);
   double ld_24 = getFreeMarginInBaseCurrency();
   int l_leverage_32 = AccountLeverage();
   int li_36 = 1 / MarketInfo(g_symbol_380, MODE_LOTSTEP);
   int li_40 = 100000;
   if (isFixedMaxOrder_Size()) {
      ld_16 = convertToBaseCurrency(MarketInfo(g_symbol_380, MODE_MARGINREQUIRED));
      l_leverage_32 = 100;
      li_40 = 100;
   }
   double ld_ret_44 = MathFloor(gd_340 * li_36 * (ld_24 / ld_16 / (li_40 / 100) * (l_leverage_32 / 100))) / li_36;
   return (ld_ret_44);
}

void updateTrailingStop(string as_0, int a_magic_8, double a_pips_12) {
   int l_cmd_28;
   double l_price_32;
   double l_point_44;
   bool l_bool_52;
   int l_ord_total_20 = OrdersTotal();
   for (int l_pos_24 = l_ord_total_20 - 1; l_pos_24 >= 0; l_pos_24--) {
      if (OrderSelect(l_pos_24, SELECT_BY_POS, MODE_TRADES)) {
         l_cmd_28 = OrderType();
         if (l_cmd_28 == OP_BUY || l_cmd_28 == OP_SELL) {
            if (OrderMagicNumber() == a_magic_8 || a_magic_8 == 0 && StringFind(OrderSymbol(), as_0, 0) != -1) {
               l_point_44 = MarketInfo(as_0, MODE_POINT);
               if (OrderType() == OP_BUY) l_price_32 = MarketInfo(as_0, MODE_BID);
               else l_price_32 = MarketInfo(as_0, MODE_ASK);
               log("TS eval: OrderStopLoss=" + OrderStopLoss() + " stopLossOffset=" + (a_pips_12 * l_point_44) + " price=" + l_price_32 + " OP_BUY =" + ((l_cmd_28 == OP_BUY)));
               if (OrderStopLoss() < l_price_32 - l_point_44 * a_pips_12 - 0.000001 && l_cmd_28 == OP_BUY) {
                  log("TS update: ---  OrderStopLoss=" + OrderStopLoss() + " stopLossOffset=" + (a_pips_12 * l_point_44) + " price=" + l_price_32 + " OrderOpenPrice=" + OrderOpenPrice() +
                     " OP_BUY =" + ((l_cmd_28 == OP_BUY)));
                  l_bool_52 = OrderModify(OrderTicket(), OrderOpenPrice(), l_price_32 - l_point_44 * a_pips_12, OrderTakeProfit(), 0, Blue);
                  if (l_bool_52 != TRUE) log("Failed TS update!!! error=" + GetLastError());
               }
               if (OrderStopLoss() > l_price_32 + l_point_44 * a_pips_12 + 0.000001 && l_cmd_28 == OP_SELL) OrderModify(OrderTicket(), OrderOpenPrice(), l_price_32 + l_point_44 * a_pips_12, OrderTakeProfit(), 0, Blue);
            }
         }
      }
   }
}

void log(string as_0) {
   int li_12 = TimeLocal();
   li_12 -= 18000;
   string ls_16 = "";
   ls_16 = "" + TimeYear(li_12);
   ls_16 = ls_16 + "-" + TimeMonth(li_12);
   ls_16 = ls_16 + "-" + TimeDay(li_12);
   int l_file_8 = FileOpen("log_mania_slave_expert_" + ls_16 + ".csv", FILE_CSV|FILE_WRITE|FILE_READ, ';');
   if (l_file_8 > 0) {
      FileSeek(l_file_8, 0, SEEK_END);
      FileWrite(l_file_8, ls_16 + " " + TimeHour(li_12) + ":" + TimeMinute(li_12) + ":" + TimeSeconds(li_12), as_0);
      FileClose(l_file_8);
   }
}

int isOnHalfHour() {
   int l_datetime_0 = TimeCurrent();
   if (TimeMinute(l_datetime_0) == 0 || TimeMinute(l_datetime_0) == 30) return (1);
   return (0);
}