#property copyright "bonten"
#property link      "bd0ppens@gmail.com"

#include <stdlib.mqh>

extern double Lot = 0.1;
extern double MinimumMargin = 100.0;
extern int Magic = 56757;
extern double TakeProfit = 0.0;
extern int Smoothing = 60;
extern int Timeframe = 5;

int g_ticket_number = -1;
datetime g_current_time;

int ENTRY_BUY = 0;
int ENTRY_SELL = 1;
int ENTRY_NONE = 2;

int init() 
{
   set_bar_time();
   return (0);
}

int deinit() 
{
   return (0);
}

double get_qqe(int mode, int idx)
{
   return (iCustom(
      NULL, 
      0, 
      "QQE_Alert_MTF_v5", 
   //indicator input params - start
      Smoothing,
      Timeframe,
      "",
      false,
      false,
      false,
      false,
      false,
      false,
      "",
      "",
      "",
      "",
      "",
      "",
      "",
      "",
      "",
      "",
      "",
      "",
      "",
      "",
      "",
      false,
      false,
      false,
      false,
      false,
      false,
      "",
      CLR_NONE,
      CLR_NONE,
      CLR_NONE,
      CLR_NONE,
      CLR_NONE,
      CLR_NONE,
      "",
      30,
   //indicator input params - end
      mode,
      idx));
}

int get_entry()
{
   if ((get_qqe(0, 1) > get_qqe(2, 1) && get_qqe(0, 2) < get_qqe(2, 2)) ||
      (get_qqe(0, 1) > get_qqe(2, 1) && get_qqe(0, 2) == get_qqe(2, 2) && get_qqe(0, 3) < get_qqe(2, 3)))
   {
      Print("get_qqe(0, 1): ", get_qqe(0, 1), " - get_qqe(2, 1): ", get_qqe(2, 1), " - get_qqe(0, 2): ", get_qqe(0, 2),
         " - get_qqe(2, 2): ", get_qqe(2, 2), " - get_qqe(0, 3): ", get_qqe(0, 3), " - get_qqe(2, 3): ", get_qqe(2, 3));
      return (ENTRY_BUY);
   }
   
   if ((get_qqe(0, 1) < get_qqe(2, 1) && get_qqe(0, 2) > get_qqe(2, 2)) ||
      (get_qqe(0, 1) < get_qqe(2, 1) && get_qqe(0, 2) == get_qqe(2, 2) && get_qqe(0, 3) > get_qqe(2, 3)))
   {
       Print("get_qqe(0, 1): ", get_qqe(0, 1), " - get_qqe(2, 1): ", get_qqe(2, 1), " - get_qqe(0, 2): ", get_qqe(0, 2),
         " - get_qqe(2, 2): ", get_qqe(2, 2), " - get_qqe(0, 3): ", get_qqe(0, 3), " - get_qqe(2, 3): ", get_qqe(2, 3));
      return (ENTRY_SELL);
   }
   return (ENTRY_NONE);
}

void set_params(int dir, int& mode, double& tp, int& col)
{
   if (dir == OP_BUY)
   {
      mode = MODE_ASK;
      col = Blue;
      if (TakeProfit > 0.0) tp = Ask + TakeProfit * Point;
   }
   else if (dir == OP_SELL)
   {
      mode = MODE_BID;
      col = Red;
      if (TakeProfit > 0.0) tp = Bid - TakeProfit * Point;
   } 
}

void open_order(int dir, double& lot, int& ticket_number)
{
   int bid_ask;
   int col;
   int slipage = 3;
   double tp = 0.0;
   int last_err;
   
   set_params(dir, bid_ask, tp, col); 
   ticket_number = OrderSend(Symbol(), dir, lot, MarketInfo(Symbol(), bid_ask), slipage, 0.0, tp, "NinpostarRevolution_bonten", Magic, 0, col);
   last_err = GetLastError();
   Print(ticket_number);
   Print(last_err);
   while (ticket_number == -1 && (last_err == 138 || last_err == 129 || last_err == 146))
   {
      RefreshRates();
      set_params(dir, bid_ask, tp, col); 
      ticket_number = OrderSend(Symbol(), dir, lot, MarketInfo(Symbol(), bid_ask), slipage, 0.0, tp, "NinpostarRevolution_bonten", Magic, 0, col);
      last_err = GetLastError();
   }
}

bool is_order_open(int ticket_number)
{  
   OrderSelect(ticket_number, SELECT_BY_TICKET);
   return (ticket_number != -1 && OrderCloseTime() == 0 && OrderMagicNumber() == Magic);
}

void close_order(int ticket_number, int dir)
{
   int bid_ask;
   int col;
   bool res;
   int last_err;
   int slipage = 3;
   
   if (dir == OP_BUY) 
   {
      bid_ask = MODE_BID;
      col = Blue;
   }
   else if (dir == OP_SELL)
   {
      bid_ask = MODE_ASK;
      col = Red;
   }

   OrderSelect(ticket_number, SELECT_BY_TICKET);
   res = OrderClose(OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), bid_ask), slipage, col); 
   last_err = GetLastError(); 
   Print(res);
   Print(last_err);
   int count  = 0;
   while (!res && (last_err == 138 || last_err == 129 || last_err == 146))
   {
      if (count >= 1000 && (count % 1000 == 0)) Print(last_err);
      RefreshRates();
      res = OrderClose(OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), bid_ask), slipage, col);  
      last_err = GetLastError();
      count++;
   }
}

bool is_same_bar_time()
{
   return (Time[0] == g_current_time);
}

void set_bar_time()
{
   g_current_time = Time[0];
}

int start() 
{
   if (AccountFreeMargin() > MinimumMargin && !is_same_bar_time())
   {
      if (get_entry() == ENTRY_BUY)
      {
         if (is_order_open(g_ticket_number)) close_order(g_ticket_number, OP_SELL);
         open_order(OP_BUY, Lot, g_ticket_number);
         set_bar_time();
      }
      else if (get_entry() == ENTRY_SELL)
      {
         if (is_order_open(g_ticket_number)) close_order(g_ticket_number, OP_BUY);
         open_order(OP_SELL, Lot, g_ticket_number);
         set_bar_time();
      }
   }
   return (0);
}

     