//+------------------------------------------------------------------+
//|                                           # SP GOLD ver. 0.2.mq4 |
//|                                     Copyright 2014, Kolosov D.E. |
//|                                          Идея: Stanislav Korolev |
//|                                      Тестировали: senyabo, Ktych |
//+------------------------------------------------------------------+
#property copyright "Copyright 2014, Kolosov D.E. "

extern string  строка_1                   =  "Настройка 1-го ордера";
extern int     тэйкпрофит_1               =  5000;
extern int     стоплосс_1                 =  1000;
extern int     отступ                     =  350;
extern string  строка_2                   =  "Безубыток 1-го";
extern int     скок_пунктов_пройдено_1    =  500;
extern int     скок_пунктов_в_бу_1        =  100;
extern string  строка_3                   =  "Настройка 2-го ордера";
extern bool    открывать_второй_ордер_?   =  true;
extern int     тэйкпрофит_2               =  2000;
extern int     стоплосс_2                 =  600;
extern string  строка_4                   =  "Безубыток 2-го";
extern int     скок_пунктов_пройдено_2    =  500;
extern int     скок_пунктов_в_бу_2        =  100;
extern string  строка_5                   =  "Параметры HMA";
extern int     период                     =  30;
extern int     метод                      =  3;
extern string  строка_6                   =  "Настройки лота";
extern double  лот                        =  0.1;                 // Если лот равен нулю, то используется автоММ
extern double  риск                       =  1;                   // Процент риска на сделку
extern string  строка_7                   =  "Прочие настройки";
extern int     проскальзывание            =  70;
extern int     магический_номер           =  80190283;
extern string  строка_8                   =  "Настройки инфопанели";
extern bool    показывать_инфопанель_?    =  true;
extern color   colortext                  =  Black;

int     corner      =  0;
int     coord_y     =  16;
int     text_size   =  8;

int    bar = 0;
double n   = 1.0;
int    name_n = 16;
string name[];

int init() 
{
   if (Digits == 3) { 
      тэйкпрофит_1            *= 10;
      стоплосс_1              *= 10;
      отступ                  *= 10;
      скок_пунктов_пройдено_1 *= 10;
      скок_пунктов_в_бу_1     *= 10;
      тэйкпрофит_2            *= 10;
      стоплосс_2              *= 10;
      скок_пунктов_пройдено_2 *= 10;
      скок_пунктов_в_бу_2     *= 10;
      проскальзывание         *= 10;
   }
   if (ObjectFind("BKGR") >= 0) ObjectDelete("BKGR");
   if (ObjectFind("BKGP") >= 0) ObjectDelete("BKGP");
   if (ObjectFind("BKGO") >= 0) ObjectDelete("BKGO");
   if (ObjectFind("BKGH") >= 0) ObjectDelete("BKGH");
   if (ObjectFind("BKGI") >= 0) ObjectDelete("BKGI");
   
   ArrayResize(name,name_n);
   for (int i = 0; i < name_n; i++) name[i] = "x_" + DoubleToStr(i,0);
   
   return(0);
}

int deinit()
{
   Comment("");
   if (ObjectFind("BKGR") >= 0) ObjectDelete("BKGR");
   if (ObjectFind("BKGP") >= 0) ObjectDelete("BKGP");
   if (ObjectFind("BKGO") >= 0) ObjectDelete("BKGO");
   if (ObjectFind("BKGH") >= 0) ObjectDelete("BKGH");
   if (ObjectFind("BKGI") >= 0) ObjectDelete("BKGI");

   for (int i = 0; i < name_n; i++) ObjectDelete(name[i]);
      
   return(0);
}

int start()
{
   double hma0 = 0.0, hma1 = 0.0, hma2 = 0.0, hma3 = 0.0;
   bool   buy  = false,
          sell = false;
   
   if (bar != Bars) {
      hma0 = iCustom(Symbol(),NULL,"# HMA",период,метод,0,0,1,0,0);
      hma1 = iCustom(Symbol(),NULL,"# HMA",период,метод,0,0,1,0,1);
      hma2 = iCustom(Symbol(),NULL,"# HMA",период,метод,0,0,1,0,2);
      hma3 = iCustom(Symbol(),NULL,"# HMA",период,метод,0,0,1,0,3);

      if (hma3 > hma2 && hma2 < hma1 && hma1 < hma0) {
         buy = true;
      } else buy = false;
      
      if (hma3 < hma2 && hma2 > hma1 && hma1 > hma0) {
         sell = true;
      } else sell = false;
      
      if (buy == true) {
         if (количество_ордеров(OP_BUY) == 0 || количество_ордеров(OP_BUYSTOP) == 0) {
            if (количество_ордеров(OP_BUYSTOP)  != 0) Close_All(OP_BUYSTOP);
            if (количество_ордеров(OP_SELLSTOP) != 0) Close_All(OP_SELLSTOP);
            открыть_отложенный_ордер(OP_BUYSTOP,High[1] + отступ*Point,1);
            if (открывать_второй_ордер_?) 
               открыть_отложенный_ордер(OP_BUYSTOP,High[1] + отступ*Point,2);
            bar = Bars;
         }
      }
      
      if (sell == true) {
         if (количество_ордеров(OP_SELL) == 0 || количество_ордеров(OP_SELLSTOP) == 0) {
            if (количество_ордеров(OP_BUYSTOP)  != 0) Close_All(OP_BUYSTOP);
            if (количество_ордеров(OP_SELLSTOP) != 0) Close_All(OP_SELLSTOP);  
            открыть_отложенный_ордер(OP_SELLSTOP,Low[1] - отступ*Point,1);
            if (открывать_второй_ордер_?) 
               открыть_отложенный_ордер(OP_SELLSTOP,Low[1] - отступ*Point,2);
            bar = Bars;       
         }
      }
   }
      
   if (количество_ордеров(-2) != 0) {
      for (int i = OrdersTotal()-1; i >= 0; i--) {
         if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
            if (OrderSymbol() != Symbol() || OrderMagicNumber() != магический_номер) continue;
            if (OrderSymbol() == Symbol() && OrderMagicNumber() == магический_номер) {
               if (OrderType() == OP_BUY) {
                  if (OrderComment() == "SP GOLD ver. 0.2. Бай №1") {
                     if (((Ask+Bid)/2.0 - OrderOpenPrice()) > скок_пунктов_пройдено_1*Point && OrderStopLoss() < OrderOpenPrice()) {
                        if (!OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice() + скок_пунктов_в_бу_1*Point,OrderTakeProfit(),0,Yellow))
                           Print("Не удалось модифицировать ордер на покупку №" + OrderTicket() + ". Ошибка " + GetLastError());
                     }
                  } else if (OrderComment() == "SP GOLD ver. 0.2. Бай №2") {
                     if (((Ask+Bid)/2.0 - OrderOpenPrice()) > скок_пунктов_пройдено_2*Point && OrderStopLoss() < OrderOpenPrice()) {
                        if (!OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice() + скок_пунктов_в_бу_2*Point,OrderTakeProfit(),0,Yellow))
                           Print("Не удалось модифицировать ордер на покупку №" + OrderTicket() + ". Ошибка " + GetLastError());
                     }
                  }
               }
               if (OrderType() == OP_SELL) {
                  if (OrderComment() == "SP GOLD ver. 0.2. Сэл №1") {
                     if ((OrderOpenPrice() - (Ask+Bid)/2.0) > скок_пунктов_пройдено_1*Point && OrderStopLoss() > OrderOpenPrice()) {
                        if (!OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice() - скок_пунктов_в_бу_1*Point,OrderTakeProfit(),0,Yellow))
                           Print("Не удалось модифицировать ордер на продажу №" + OrderTicket() + ". Ошибка " + GetLastError());
                     }
                  } else if (OrderComment() == "SP GOLD ver. 0.2. Сэл №2") {
                     if ((OrderOpenPrice() - (Ask+Bid)/2.0) > скок_пунктов_пройдено_2*Point && OrderStopLoss() > OrderOpenPrice()) {
                        if (!OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice() - скок_пунктов_в_бу_2*Point,OrderTakeProfit(),0,Yellow))
                           Print("Не удалось модифицировать ордер на продажу №" + OrderTicket() + ". Ошибка " + GetLastError());
                     }
                  } 
               }
            }
         }
      }
   }
   
   if (показывать_инфопанель_?) {
     /* if (!IsTesting()) */            // Эту строку закоментировать!!!!!
      сбор_и_отображение_инфы();
   }
      
   return(0);
}

int открыть_отложенный_ордер(int тип, double цена_открытия, int номер_ордера)
{
   int ticket = 0;
   double tp = 0.0, sl = 0.0;
   string комментарий = "";
 
   if (тип == OP_BUYSTOP) {
      if (номер_ордера == 1) {
         tp = NormalizeDouble(цена_открытия + тэйкпрофит_1*Point, Digits);
         sl = NormalizeDouble(цена_открытия - стоплосс_1*Point,   Digits);
         комментарий = "SP GOLD ver. 0.2. Бай №1";
      } else if (номер_ордера == 2) {
         tp = NormalizeDouble(цена_открытия + тэйкпрофит_2*Point, Digits);
         sl = NormalizeDouble(цена_открытия - стоплосс_2*Point,   Digits);
         комментарий = "SP GOLD ver. 0.2. Бай №2";
      }
      ticket = OrderSend(Symbol(),OP_BUYSTOP,  рассчёт_лота(),цена_открытия,проскальзывание,sl,tp,комментарий,магический_номер,0,Yellow);
      if (ticket < 0) Print("Ордер BuyStop по цене " + DoubleToStr(цена_открытия,Digits) + " не был открыт. Ошибка " + GetLastError());
   }
   
   if (тип == OP_SELLSTOP) {
      if (номер_ордера == 1) {
         tp = NormalizeDouble(цена_открытия - тэйкпрофит_1*Point, Digits);
         sl = NormalizeDouble(цена_открытия + стоплосс_1*Point,   Digits);
         комментарий = "SP GOLD ver. 0.2. Сэл №1";
      } else if (номер_ордера == 2) {
         tp = NormalizeDouble(цена_открытия - тэйкпрофит_2*Point, Digits);
         sl = NormalizeDouble(цена_открытия + стоплосс_2*Point,   Digits);
         комментарий = "SP GOLD ver. 0.2. Сэл №2";
      }
      ticket = OrderSend(Symbol(),OP_SELLSTOP, рассчёт_лота(),цена_открытия,проскальзывание,sl,tp,комментарий,магический_номер,0,Yellow);
      if (ticket < 0) Print("Ордер SellStop по цене " + DoubleToStr(цена_открытия,Digits) + " не был открыт. Ошибка " + GetLastError());
   }
   return (ticket);
}

int количество_ордеров(int тип_ордера)
{
   int счётчик = 0;
   for (int ордер = OrdersTotal() - 1; ордер >= 0; ордер--) {
      if (OrderSelect(ордер, SELECT_BY_POS, MODE_TRADES)) {
         if (OrderSymbol() != Symbol() || OrderMagicNumber() != магический_номер) continue;
         if (OrderSymbol() == Symbol() && OrderMagicNumber() == магический_номер) {
            if (тип_ордера == OP_BUY       && OrderType() == тип_ордера) счётчик++;
            if (тип_ордера == OP_SELL      && OrderType() == тип_ордера) счётчик++;
            if (тип_ордера == OP_BUYLIMIT  && OrderType() == тип_ордера) счётчик++;
            if (тип_ордера == OP_BUYSTOP   && OrderType() == тип_ордера) счётчик++;
            if (тип_ордера == OP_SELLLIMIT && OrderType() == тип_ордера) счётчик++;
            if (тип_ордера == OP_SELLSTOP  && OrderType() == тип_ордера) счётчик++;
            if (тип_ордера == -2)                                        счётчик++;
         }
      }
   }
   return (счётчик);
}

bool Close_All(int type)
{
   bool error = true;
   int err, nn, OT;
   string Symb;
   while (true) {
      for (int j = OrdersTotal()-1; j >= 0; j--) {
         if (OrderSelect(j, SELECT_BY_POS)) {
            Symb = OrderSymbol();
            if (Symb == Symbol() && OrderMagicNumber() == магический_номер) {
               OT = OrderType();
               if (type == OP_BUYSTOP  && OT == OP_BUYSTOP)  OrderDelete(OrderTicket());
               if (type == OP_SELLSTOP && OT == OP_SELLSTOP) OrderDelete(OrderTicket());
               
               if (!error) {
                  err = GetLastError();
                  if (err < 2) continue;
                  if (err == 129) {  
                     Comment("Неправильная цена ",TimeToStr(TimeCurrent(),TIME_MINUTES));
                     Sleep(5000);
                     RefreshRates();
                     continue;
                  }
                  if (err == 146) {
                     if (IsTradeContextBusy()) Sleep(2000);
                     continue;
                  }
                  Comment("Ошибка ",err," закрытия ордера N ",OrderTicket(),
                          "     ",TimeToStr(TimeCurrent(),TIME_MINUTES));
               }
            }
         }
      }
      int n = 0;
      for (j = 0; j < OrdersTotal(); j++) {
         if (OrderSelect(j, SELECT_BY_POS)) {
            if (OrderSymbol() == Symbol() && OrderMagicNumber() == магический_номер) {
               OT = OrderType();
               if (OT == type) n++;
            }
         }  
      }
      if (n == 0) break;
      nn++;
      Sleep(1000);
      RefreshRates();
   }
   return(1);
}

double рассчёт_лота()
{
   if (лот != 0.0) return (лот);
   
   double Free    = AccountFreeMargin();
   
   double LotVal  = MarketInfo(Symbol(),MODE_TICKVALUE)/(MarketInfo(Symbol(),MODE_TICKSIZE)/MarketInfo(Symbol(),MODE_POINT)); //стоимость 1 пункта для 1 лота
   double Min_Lot = MarketInfo(Symbol(),MODE_MINLOT);
   double Max_Lot = MarketInfo(Symbol(),MODE_MAXLOT);
   double Step    = MarketInfo(Symbol(),MODE_LOTSTEP);
   double Lot     = MathFloor((Free*риск/100)/(стоплосс_1*LotVal)/Step)*Step;
   
   if (Lot < Min_Lot) Lot = Min_Lot;
   if (Lot > Max_Lot) Lot = Max_Lot;
   
   Lot = NormalizeDouble(Lot,2);
   
   return (Lot);
}

void сбор_и_отображение_инфы()
{
   double прибыль = 0.0, лотность = 0.0;
   for (int i = OrdersTotal()-1; i >= 0; i--) {
      if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
         if (OrderSymbol() != Symbol() || OrderMagicNumber() != магический_номер) continue;
         if (OrderSymbol() == Symbol() && OrderMagicNumber() == магический_номер) {
            if (OrderType() < 2) {
               прибыль  += OrderProfit() + OrderSwap();
               лотность += OrderLots();
            }
         }
      }
   }
   
   string text_back = "gg";
   
   if (ObjectFind("BKGR") < 0) {
      ObjectCreate("BKGR", OBJ_LABEL, 0, 0, 0);
      ObjectSetText("BKGR", text_back, 90, "Webdings", Gray);
      ObjectSet("BKGR", OBJPROP_CORNER, 0);
      ObjectSet("BKGR", OBJPROP_BACK, TRUE);
      ObjectSet("BKGR", OBJPROP_XDISTANCE, 5);
      ObjectSet("BKGR", OBJPROP_YDISTANCE, 50);
   }
   
   if (ObjectFind("BKGP") < 0) {
      ObjectCreate("BKGP", OBJ_LABEL, 0, 0, 0);
      ObjectSetText("BKGP", text_back, 90, "Webdings", Gray);
      ObjectSet("BKGP", OBJPROP_CORNER, 0);
      ObjectSet("BKGP", OBJPROP_BACK, TRUE);
      ObjectSet("BKGP", OBJPROP_XDISTANCE, 5);
      ObjectSet("BKGP", OBJPROP_YDISTANCE, 150);
   }
   
   if (ObjectFind("BKGI") < 0) {
      ObjectCreate("BKGI", OBJ_LABEL, 0, 0, 0);
      ObjectSetText("BKGI", text_back, 90, "Webdings", Gray);
      ObjectSet("BKGI", OBJPROP_CORNER, 0);
      ObjectSet("BKGI", OBJPROP_BACK, TRUE);
      ObjectSet("BKGI", OBJPROP_XDISTANCE, 5);
      ObjectSet("BKGI", OBJPROP_YDISTANCE, 200);
   }
   
   if (ObjectFind("BKGO") < 0) {
      ObjectCreate("BKGO", OBJ_LABEL, 0, 0, 0);
      ObjectSetText("BKGO", "SP GOLD ver. 0.2", 12, "Tahoma Bold", DodgerBlue);
      ObjectSet("BKGO", OBJPROP_CORNER, 0);
      ObjectSet("BKGO", OBJPROP_BACK, false);
      ObjectSet("BKGO", OBJPROP_XDISTANCE, 60);
      ObjectSet("BKGO", OBJPROP_YDISTANCE, 23);
   }
   
   if (ObjectFind("BKGH") < 0) {
      ObjectCreate("BKGH", OBJ_LABEL, 0, 0, 0);
      ObjectSetText("BKGH", text_back, 90, "Webdings", FireBrick);
      ObjectSet("BKGH", OBJPROP_CORNER, 0);
      ObjectSet("BKGH", OBJPROP_BACK, true);
      ObjectSet("BKGH", OBJPROP_XDISTANCE, 5);
      ObjectSet("BKGH", OBJPROP_YDISTANCE, 15);
   }
   
   string all_text[];
   ArrayResize(all_text,name_n);
   int    otstup_cleva = 20;
   
   all_text[0] = " | Первый ордер: ";
   SetLabel(name[0], all_text[0], colortext, otstup_cleva, coord_y + 40, corner, text_size);
   
   all_text[1] = " | ТП = " + тэйкпрофит_1 + " пп / СЛ = " + стоплосс_1 + " пп";
   SetLabel(name[1], all_text[1], colortext, otstup_cleva, coord_y + 55, corner, text_size);
   
   all_text[2] = " | Безубыток при достижении " + скок_пунктов_пройдено_1 + " пп";
   SetLabel(name[2], all_text[2], colortext, otstup_cleva, coord_y + 70, corner, text_size);
   
   all_text[3] = " | Ордеров в рынке: " + DoubleToStr(количество_ордеров(OP_BUY) + количество_ордеров(OP_BUYSTOP),0);
   SetLabel(name[3], all_text[3], colortext, otstup_cleva, coord_y + 85, corner, text_size);
   
   // ---------------------------------------------------------------------------------------------------------------- //
   
   if (открывать_второй_ордер_?)  all_text[4] = " | Второй ордер: Enabled";
   if (!открывать_второй_ордер_?) all_text[4] = " | Второй ордер: Disabled";
   SetLabel(name[4], all_text[4], colortext, otstup_cleva, coord_y + 105, corner, text_size);
   
   all_text[5] = " | ТП = " + тэйкпрофит_2 + " пп / СЛ = " + стоплосс_2 + " пп";
   SetLabel(name[5], all_text[5], colortext, otstup_cleva, coord_y + 120, corner, text_size);
   
   all_text[6] = " | Безубыток при достижении " + скок_пунктов_пройдено_2 + " пп";
   SetLabel(name[6], all_text[6], colortext, otstup_cleva, coord_y + 135, corner, text_size);
   
   all_text[7] = " | Ордеров в рынке: " + DoubleToStr(количество_ордеров(OP_SELL) + количество_ордеров(OP_SELLSTOP),0);
   SetLabel(name[7], all_text[7], colortext, otstup_cleva, coord_y + 150, corner, text_size);
   
   // ---------------------------------------------------------------------------------------------------------------- //
   
   all_text[8] = " | ------------------------------------------------- | ";
   SetLabel(name[8], all_text[8], colortext, otstup_cleva, coord_y + 165, corner, text_size);
   
   // ---------------------------------------------------------------------------------------------------------------- //
   
   all_text[9] = " | Прибыль в валюте депозита: " + DoubleToStr(прибыль,2) + " " + AccountCurrency();
   SetLabel(name[9], all_text[9], colortext, otstup_cleva, coord_y + 180, corner, text_size);

   all_text[10] = " | Суммарный лот: " + DoubleToStr(лотность,2);
   SetLabel(name[10], all_text[10], colortext, otstup_cleva, coord_y + 195, corner, text_size);
   
   all_text[11] = " | Текущей спред: " + DoubleToStr(MarketInfo(Symbol(),MODE_SPREAD),1);
   SetLabel(name[11], all_text[11], colortext, otstup_cleva, coord_y + 210, corner, text_size);
   
   // ---------------------------------------------------------------------------------------------------------------- //
   
   all_text[12] = " | ------------------------------------------------- | ";
   SetLabel(name[12], all_text[12], colortext, otstup_cleva, coord_y + 225, corner, text_size);
   
   // ---------------------------------------------------------------------------------------------------------------- //
   
   all_text[13] = " | Баланс:  " + DoubleToStr(AccountBalance(),2);
   SetLabel(name[13], all_text[13], colortext, otstup_cleva, coord_y + 240, corner, text_size);
   
   all_text[14] = " | Эквити:  " + DoubleToStr(AccountEquity(),2);
   SetLabel(name[14], all_text[14], colortext, otstup_cleva, coord_y + 255, corner, text_size);
   
   // ---------------------------------------------------------------------------------------------------------------- //
   
   all_text[15] = " | ------------------------------------------------- | ";
   SetLabel(name[15], all_text[15], colortext, otstup_cleva, coord_y + 270, corner, text_size);
   
   // ---------------------------------------------------------------------------------------------------------------- //   
}

//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    nm - наименование объекта                                               |
//|    tx - текст                                                              |
//|    cl - цвет метки                                                         |
//|    xd - координата X в пикселах                                            |
//|    yd - координата Y в пикселах                                            |
//|    cr - номер угла привязки        (0 - левый верхний)                     |
//|    fs - размер шрифта              (8 - по умолчанию)                      |
//+----------------------------------------------------------------------------+
void SetLabel(string nm, string tx, color cl, int xd, int yd, int cr, int fs) {
  if (ObjectFind(nm) < 0) ObjectCreate(nm, OBJ_LABEL, 0, 0,0);
  ObjectSetText(nm, tx, fs);
  ObjectSet(nm, OBJPROP_COLOR    , cl);
  ObjectSet(nm, OBJPROP_XDISTANCE, xd);
  ObjectSet(nm, OBJPROP_YDISTANCE, yd);
  ObjectSet(nm, OBJPROP_CORNER   , cr);
  ObjectSet(nm, OBJPROP_FONTSIZE , fs);
}
//+----------------------------------------------------------------------------+