//+------------------------------------------------------------------+
//|                                                Fracktal_Grid.mq4 |
//|                                                           AVMOHR |
//+------------------------------------------------------------------+
#property copyright "AVMOHR"
#property link      ""
extern string rem="������ �� ���������� � ��";
extern int Vertikal_shift=3;
extern string rem10="��� ������ ������";
extern int Time_start_Market=10;
extern string rem11="��� ��������� ������";
extern int Time_stop_Market=22;
extern string rem1=" ��������� ������";
extern int StopLoss=50;
extern int TakeProfit=100;
extern int Trailing=15;
extern int Step_Tral=3;
extern string rem2="���������� � �/� ��� ����������";
extern int Level_NoLoss=10;
extern string rem21="�� ������� ���������� �/�";
extern int No_Loss=2;
extern bool Use_Spread=true;
extern string rem3="�������� ���������";
extern double Lots=0.2;
extern string rem31="���� ���=0, �� ������� �������� �� ��������";
extern double Percent=1;
extern int Max_Lot=10;
extern string rem32="����� ������";
extern int Magik=112233;
extern string rem4="����������� ������� �� �������";
extern int History=5;
extern string rem5="������� ��� ������ � �������";
extern bool Close_Friday=true;
extern string rem6="����� �� ��� �������� � �������";
extern int Time_Stop=23;
extern int Minute_Stop=33;
extern string rem51="�������� ������ ������";
extern bool Use_alert=false;
double Fraktal_Prise_Up[];
double Fraktal_Prise_Down[];
datetime Time_Open_order_Up=0;     //  ����� �������� ������ ���
datetime Time_Open_order_Down=0;   //  ����� �������� ������ ����
datetime Time_Fraktal_Up=0;
datetime Time_Fraktal_Down=0;
bool Init_refresh=false;
bool Work=true;
int Time_start, Time_stop;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
Open_history_orders();
Init_refresh=true;
Time_start = Time_start_Market;
Time_stop = Time_stop_Market;
  if (Period() >= 241 ) { Time_start = 0; Time_stop = 24; }

//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
 Order_Close();  
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//----
if (Close_Friday == true)
  if ( DayOfWeek() >= 5 && Hour() >= Time_Stop && Minute() >= Minute_Stop) { Order_Close(); return(0); }
  
  if  (Init_refresh == false)  { Open_history_orders(); Init_refresh=true; }
  Find_orders();
  double Open_Prise;
  int Direct_order=0;
  Fraktal_prise_real(Direct_order, Open_Prise);
  if (Direct_order == 1 && Time_Open_order_Up != Time_Fraktal_Up ) 
      {
       Open_Buy(Open_Prise); 
       Time_Open_order_Up = Time_Fraktal_Up; 
      }
  if (Direct_order == -1 && Time_Open_order_Down != Time_Fraktal_Down ) 
      {
       Open_Sell(Open_Prise); 
       Time_Open_order_Down = Time_Fraktal_Down; 
      }
//----
if ( GetLastError() != 0 && Use_alert == true ) { Alert(ErrorDescription(GetLastError())); }
   return(0);
  }
//+------------------------------------------------------------------+


//----------------------------------------------------------------------
//  ������� ������� ������� ����
//----------------------------------------------------------------------
double Lot_Refresh() 
  {
   double New_Lot;
   double One_Lot=MarketInfo(Symbol(),MODE_MARGINREQUIRED);   //   ������ ��������� �������, ����������� ��� �������� 1 ���� �� �������
   double Min_Lot=MarketInfo(Symbol(),MODE_MINLOT);
   double Step   =MarketInfo(Symbol(),MODE_LOTSTEP);
   double Free   =AccountFreeMargin();
//-----------------------------------------------------------------
   if (Lots > 0)                                 // ���� ������ ����..
     {
      double Money=Lots*One_Lot;
      if(Money<=AccountFreeMargin())
         New_Lot=Lots;
      else                                     // ���� �� ������� �������
         New_Lot=MathFloor(Free/One_Lot/Step)*Step;
     }
   else                                        // ���� ���� �� ������
     {
      if (Percent > 100) Percent=100;
      if (Percent <=0 ) Percent=0.01;
      if (Percent==0) New_Lot=Min_Lot;
      else
         New_Lot=MathFloor(Free*Percent/100/One_Lot/Step)*Step;
     }

   if (New_Lot < Min_Lot)                     // ���� ������ �����������
      New_Lot=Min_Lot;
   if (New_Lot*One_Lot > AccountFreeMargin()) // �� ������� ����..
     {
      Alert("�� ������� ������� �� �������� ������");
      return(0);
     }
   if (Max_Lot <= New_Lot ) New_Lot=Max_Lot;
   return(New_Lot);
  }

//----------------------------------------------------------------------
//  ������� ������� ������
//----------------------------------------------------------------------
void Stop_Profit(int Direct, double &SL, double &TP, double Prise_ord)
{ 
  int Min_Stop=MarketInfo(Symbol(), MODE_STOPLEVEL);
   if (SL !=0 && SL < Min_Stop ) SL=Min_Stop;          //  ���� ������� ������ ������ �����������, �� ������ ���������� ����������
   if (TP !=0 && TP < Min_Stop ) TP=Min_Stop;
  double Spread=MarketInfo(Symbol(), MODE_SPREAD);
  if ( Use_Spread == false ) Spread=0;
  if ( Direct >= 1 ) //  ���� ������ �� �������
   { 
     if (SL !=0 )      SL = Prise_ord-(SL-Spread)*Point;      else SL=0;
     if (TP !=0 )      TP = Prise_ord+(TP+Spread)*Point;      else TP=0;
   }
  if ( Direct <= -1 ) //  ���� ������ �� �������
   {
     if (SL !=0)       SL = Prise_ord+(SL-Spread)*Point;      else SL=0;
     if (TP !=0)       TP = Prise_ord-(TP+Spread)*Point;      else TP=0;
   }
 SL= NormalizeDouble(SL,Digits);      // ����������� �������� ������ 
 TP= NormalizeDouble(TP,Digits);      // ����������� �������� ������ 
}


//----------------------------------------------------------------------
//  ������� ������ �������� ��������� �� �������
//----------------------------------------------------------------------
void History_find(double &Up[], double &Down[] )
{
   int i=0;
   int History_bar=0;
   while (i<=History)   //   ����� ��������� �������� ������� ���������
   {
     double F_Up=iFractals(NULL,0,MODE_UPPER,History_bar);
        int F_Up_Time=TimeHour( iTime(NULL,0,History_bar) );
     double F_Down=iFractals(NULL,0,MODE_LOWER,History_bar);
        int F_Down_Time=TimeHour( iTime(NULL,0,History_bar) );
      if (F_Up != 0 && F_Up_Time >= Time_start && F_Up_Time <= Time_stop )   //   ���� �������� �� ����� ���� � ����� �������� ��� ������� ��������
       { 
         ArrayResize(Up, i+1);
         Up[i]=F_Up;
         i++;
       }
       
      if (F_Down != 0 && F_Down_Time >= Time_start && F_Down_Time <= Time_stop )  //   ���� �������� �� ����� ���� � ����� �������� ��� ������� ��������
       { 
        ArrayResize(Down, i+1);
        Down[i]=F_Down;
        i++;
       }
      
    History_bar++; 
   }
   
}

//----------------------------------------------------------------------
//  ������� ������ �������� ���������� ��������
//----------------------------------------------------------------------
void Fraktal_prise_real(int &Direct, double &Open_Prise)
{
if ( Hour() < Time_start || Hour() > Time_stop) return;
 int i=0;
 int History_bar=3;
  while (i <= 1 )
   {
     double F_Up=iFractals(NULL,0,MODE_UPPER,History_bar);
       int F_Up_Time=TimeHour( iTime(NULL,0,History_bar) );
     double F_Down=iFractals(NULL,0,MODE_LOWER,History_bar);
       int F_Down_Time=TimeHour( iTime(NULL,0,History_bar) );
     if ( F_Up !=0  && (F_Up_Time >= Time_start && F_Up_Time <= Time_stop ) ) 
       {
        Open_Prise = F_Up; 
        Time_Fraktal_Up=Time[History_bar];
        Direct=1;
        i++;
        break;
       }
       
     if ( F_Down != 0  && (F_Up_Time >= Time_start && F_Up_Time <= Time_stop ) ) 
       {
        Open_Prise = F_Down; 
        Time_Fraktal_Down=Time[History_bar];
        Direct=-1;
        i++;
        break;
       }
      History_bar++; 
   }
}

//----------------------------------------------------------------------
//  ������� ������� ���������� ������ �� ������������ ���������
//----------------------------------------------------------------------
void Open_history_orders()
{
 History_find(Fraktal_Prise_Up, Fraktal_Prise_Down);
 double Prise=iClose(NULL,0,0);
// double freez=MarketInfo(Symbol(),MODE_FREEZELEVEL);
 for (int i = History-1; i > 0; i--)
  {
   if ( Prise < (Fraktal_Prise_Up[i]))   { Open_Buy(Fraktal_Prise_Up[i]);    Time_Open_order_Up   = Time[i];   Time_Fraktal_Up = Time_Open_order_Up; }
   if ( Prise > (Fraktal_Prise_Down[i])) { Open_Sell(Fraktal_Prise_Down[i]); Time_Open_order_Down = Time[i]; Time_Fraktal_Down = Time_Open_order_Down;}
  }
   Init_refresh=true;
}

//----------------------------------------------------------------------
//  ������� ������� ���������� ����� ���
//----------------------------------------------------------------------
void Open_Buy(double Prise_order)
{
  double Lt=Lot_Refresh();
  double SL=StopLoss;
  double TP=TakeProfit;
  Prise_order=Prise_order+Vertikal_shift*Point;
  Stop_Profit(1, SL, TP, Prise_order);
  int i=0;
  while(true)
  {
   int Ticket=OrderSend(Symbol(),OP_BUYSTOP,Lt,Prise_order,5,SL,TP,"Fraktal_Grid order",Magik);
   if (Ticket !=0) break;
   i++;
   if (i >=10)  
    {
    if ( GetLastError() != 0 && Use_alert == true )  Alert("������� ������� ����� ���-���� ��������� ����� ��������� � ������� 10, ������ ",
                                                           ErrorDescription(GetLastError())); 
    break;
    }
  }
}

//----------------------------------------------------------------------
//  ������� ������� ���������� ����� ����
//----------------------------------------------------------------------
void Open_Sell(double Prise_order)
{
  double Lt=Lot_Refresh();
  double SL=StopLoss;
  double TP=TakeProfit;
  Prise_order=Prise_order-Vertikal_shift*Point;
  Stop_Profit(-1, SL, TP, Prise_order);
  int i=0;
  while(true)
  {
   int Ticket=OrderSend(Symbol(),OP_SELLSTOP,Lt,Prise_order,5,SL,TP,"Fraktal_Grid order",Magik);
   if (Ticket !=0) break;
   i++;
   if (i >=10 ) 
   {
    if ( GetLastError() != 0 && Use_alert == true )  Alert("������� ������� ����� ����-���� ��������� ����� ��������� � ������� 10, ������ ",
                                                           ErrorDescription(GetLastError())); 
    break;}
  }
}

//----------------------------------------------------------------------
//  ������� �������������
//----------------------------------------------------------------------
void Trayling(int tik)             
{
      if ( OrderSelect(tik, SELECT_BY_TICKET) == false ) return;
      if( OrderType()==OP_BUY && OrderMagicNumber()==Magik )  
        {
            if(Trailing>0)  
              {                 
               if(Bid-OrderOpenPrice()>=Point*Trailing)
                 {
                  if(OrderStopLoss()<=Bid-Point*Trailing)
                    {
                     OrderModify(OrderTicket(),OrderOpenPrice(),Bid-(Trailing-Step_Tral)*Point,OrderTakeProfit(),0,Green);
                     return(0);
                    }
                 }
              }
         }
        if( OrderType()==OP_SELL && OrderMagicNumber()==Magik )  
           {
            if(Trailing>0)  
              {                 
               if((OrderOpenPrice()-Ask)>=(Point*Trailing))
                 {
                  if((OrderStopLoss()>=(Ask+Point*Trailing)) || (OrderStopLoss()==0))
                    {
                     OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*(Trailing-Step_Tral),OrderTakeProfit(),0,Red);
                     return(0);
                    }
                 }
              }
           }
return;
}

//----------------------------------------------------------------------
//  ������� �������� ������� � ���� ��������
//----------------------------------------------------------------------
void Find_orders()
{
   for(int i=0; i<=OrdersTotal(); i++)          // ���� �������� �����
  {
      if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true) // ���� ���� ���������
        {                                       // ������ �������:
          if (OrderSymbol()!=Symbol())continue;      // �� ��� ���. �������
          if (OrderMagicNumber()!=Magik)continue;  
          int Ticket=OrderTicket();
        }
      Trayling(Ticket);
      Enter_No_Loss(Ticket);      
    }
}

//----------------------------------------------------------------------
//  ������� �������� ������� � �������
//----------------------------------------------------------------------
void Order_Close()
{
  for(int i=0; i<=OrdersTotal(); i++)          // ���� �������� �����
  {
      if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true) // ���� ���� ���������
        {                                       // ������ �������:
          if (OrderSymbol()!=Symbol())continue;      // �� ��� ���. �������
          if (OrderMagicNumber()!=Magik)continue;  
          int Ticket=OrderTicket();
          if (OrderType() != OP_BUY || OrderType() != OP_SELL ) 
          {
          int n=0;
          while(true)
          {
           if ( OrderDelete(Ticket) == true ) break;
           n++;
           if (n >=10 ) 
            {
             if ( GetLastError() != 0 && Use_alert == true )  Alert("������� ������� ����� ",Ticket," ��������� ����� ��������� � ������� 10, ������ ",
                                                           ErrorDescription(GetLastError()));            
            break;
            }
          }
          }
        }
    }
Init_refresh=false;
Work = false;
}

//----------------------------------------------------------------------
//  ������� �������� � ���������
//----------------------------------------------------------------------
void Enter_No_Loss(int Ticket)
{
   if ( OrderSelect(Ticket,SELECT_BY_TICKET) == true )                     // ���� ����� ������ ������
   {
    double Profit_Order=OrderProfit();
    double Open_Prise=OrderOpenPrice();
    double TP_Order=OrderTakeProfit();
    double SL_Order=OrderStopLoss();
   }
       if (Profit_Order > 0                                                // � ���� ����� � �����
           && MathAbs(iClose(NULL,0,0)-Open_Prise) > Level_NoLoss*Point    // � ���� ������ ������ ��������� ���������� �������
           && Level_NoLoss < TakeProfit )                                  // � ���� ������� ��������� ������ ������ �����������
    {
    if (OrderType()==0 && SL_Order < Open_Prise )     // ���� ��� ������ ���
      { 
       double New_SL=Open_Prise+No_Loss*Point;
       OrderModify(Ticket, Open_Prise, New_SL, TP_Order, 0 );
      }
    if (OrderType()==1 && SL_Order > Open_Prise)    // ���� ��� ������ ����
      {
       New_SL=Open_Prise-No_Loss*Point;
       OrderModify(Ticket,Open_Prise,New_SL,TP_Order,0);
      }
    }
}
//+--------------------------------------------------------------------------------------------------------------+
//| ���������� ������
//+--------------------------------------------------------------------------------------------------------------+
string ErrorDescription(int error) {

   string ErrorNumber="";
   //---
   switch (error) {
   case 1:     ErrorNumber = "��� ������, �� ��������� ����������";                        break;
   case 2:     ErrorNumber = "����� ������";                                               break;
   case 3:     ErrorNumber = "������������ ���������";                                     break;
   case 4:     ErrorNumber = "�������� ������ �����";                                      break;
   case 5:     ErrorNumber = "������ ������ ����������� ���������";                        break;
   case 6:     ErrorNumber = "��� ����� � �������� ��������";                              break;
   case 7:     ErrorNumber = "������������ ����";                                          break;
   case 8:     ErrorNumber = "������� ������ �������";                                     break;
   case 9:     ErrorNumber = "������������ �������� ���������� ���������������� �������";  break;
   case 64:    ErrorNumber = "���� ������������";                                          break;
   case 65:    ErrorNumber = "������������ ����� �����";                                   break;
   case 128:   ErrorNumber = "����� ���� �������� ���������� ������";                      break;
   case 129:   ErrorNumber = "������������ ����";                                          break;
   case 130:   ErrorNumber = "������������ �����";                                         break;
   case 131:   ErrorNumber = "������������ �����";                                         break;
   case 132:   ErrorNumber = "����� ������";                                               break;
   case 133:   ErrorNumber = "�������� ���������";                                         break;
   case 134:   ErrorNumber = "������������ ����� ��� ���������� ��������";                 break;
   case 135:   ErrorNumber = "���� ����������";                                            break;
   case 136:   ErrorNumber = "��� ���";                                                    break;
   case 137:   ErrorNumber = "������ �����";                                               break;
   case 138:   ErrorNumber = "����� ���� - ������";                                        break;
   case 139:   ErrorNumber = "����� ������������ � ��� ��������������";                    break;
   case 140:   ErrorNumber = "��������� ������ �������";                                   break;
   case 141:   ErrorNumber = "������� ����� ��������";                                     break;
   case 145:   ErrorNumber = "����������� ���������, ��� ��� ����� ������� ������ � �����";break;
   case 146:   ErrorNumber = "���������� �������� ������";                                 break;
   case 147:   ErrorNumber = "������������� ���� ��������� ������ ��������� ��������";     break;
   case 148:   ErrorNumber = "���������� �������� � ���������� ������� �������� ������� "; break;
   //---- 
   case 4000:  ErrorNumber = "��� ������";                                                 break;
   case 4001:  ErrorNumber = "������������ ��������� �������";                             break;
   case 4002:  ErrorNumber = "������ ������� - ��� ���������";                             break;
   case 4003:  ErrorNumber = "��� ������ ��� ����� �������";                               break;
   case 4004:  ErrorNumber = "������������ ����� ����� ������������ ������";               break;
   case 4005:  ErrorNumber = "�� ����� ��� ������ ��� �������� ����������";                break;
   case 4006:  ErrorNumber = "��� ������ ��� ���������� ���������";                        break;
   case 4007:  ErrorNumber = "��� ������ ��� ��������� ������";                            break;
   case 4008:  ErrorNumber = "�������������������� ������";                                break;
   case 4009:  ErrorNumber = "�������������������� ������ � �������";                      break;
   case 4010:  ErrorNumber = "��� ������ ��� ���������� �������";                          break;
   case 4011:  ErrorNumber = "������� ������� ������";                                     break;
   case 4012:  ErrorNumber = "������� �� ������� �� ����";                                 break;
   case 4013:  ErrorNumber = "������� �� ����";                                            break;
   case 4014:  ErrorNumber = "����������� �������";                                        break;
   case 4015:  ErrorNumber = "������������ �������";                                       break;
   case 4016:  ErrorNumber = "�������������������� ������";                                break;
   case 4017:  ErrorNumber = "������ DLL �� ���������";                                    break;
   case 4018:  ErrorNumber = "���������� ��������� ����������";                            break;
   case 4019:  ErrorNumber = "���������� ������� �������";                                 break;
   case 4020:  ErrorNumber = "������ ������� ������������ ������� �� ���������";           break;
   case 4021:  ErrorNumber = "������������ ������ ��� ������, ������������ �� �������";    break;
   case 4022:  ErrorNumber = "������� ������";                                             break;
   case 4050:  ErrorNumber = "������������ ���������� ���������� �������";                 break;
   case 4051:  ErrorNumber = "������������ �������� ��������� �������";                    break;
   case 4052:  ErrorNumber = "���������� ������ ��������� �������";                        break;
   case 4053:  ErrorNumber = "������ �������";                                             break;
   case 4054:  ErrorNumber = "������������ ������������� �������-���������";               break;
   case 4055:  ErrorNumber = "������ ����������������� ����������";                        break;
   case 4056:  ErrorNumber = "������� ������������";                                       break;
   case 4057:  ErrorNumber = "������ ��������� ����������� ����������";                    break;
   case 4058:  ErrorNumber = "���������� ���������� �� ����������";                        break;
   case 4059:  ErrorNumber = "������� �� ��������� � �������� ������";                     break;
   case 4060:  ErrorNumber = "������� �� ������������";                                    break;
   case 4061:  ErrorNumber = "������ �������� �����";                                      break;
   case 4062:  ErrorNumber = "��������� �������� ���� string";                             break;
   case 4063:  ErrorNumber = "��������� �������� ���� integer";                            break;
   case 4064:  ErrorNumber = "��������� �������� ���� double";                             break;
   case 4065:  ErrorNumber = "� �������� ��������� ��������� ������";                      break;
   case 4066:  ErrorNumber = "����������� ������������ ������ � ��������� ����������";     break;
   case 4067:  ErrorNumber = "������ ��� ���������� �������� ��������";                    break;
   case 4099:  ErrorNumber = "����� �����";                                                break;
   case 4100:  ErrorNumber = "������ ��� ������ � ������";                                 break;
   case 4101:  ErrorNumber = "������������ ��� �����";                                     break;
   case 4102:  ErrorNumber = "������� ����� �������� ������";                              break;
   case 4103:  ErrorNumber = "���������� ������� ����";                                    break;
   case 4104:  ErrorNumber = "������������� ����� ������� � �����";                        break;
   case 4105:  ErrorNumber = "�� ���� ����� �� ������";                                    break;
   case 4106:  ErrorNumber = "����������� ������";                                         break;
   case 4107:  ErrorNumber = "������������ �������� ���� ��� �������� �������";            break;
   case 4108:  ErrorNumber = "�������� ����� ������";                                      break;
   case 4109:  ErrorNumber = "�������� �� ���������";                                      break;
   case 4110:  ErrorNumber = "������� ������� �� ���������";                               break;
   case 4111:  ErrorNumber = "�������� ������� �� ���������";                              break;
   case 4200:  ErrorNumber = "������ ��� ����������";                                      break;
   case 4201:  ErrorNumber = "��������� ����������� �������� �������";                     break;
   case 4202:  ErrorNumber = "������ �� ����������";                                       break;
   case 4203:  ErrorNumber = "����������� ��� �������";                                    break;
   case 4204:  ErrorNumber = "��� ����� �������";                                          break;
   case 4205:  ErrorNumber = "������ ��������� �������";                                   break;
   case 4206:  ErrorNumber = "�� ������� ��������� �������";                               break;
   case 4207:  ErrorNumber = "������ ��� ������ � ��������";                               break;
   }
   //---
   return (ErrorNumber);
}