
#property library
#include <stderror.mqh>
#include <WinUser32.mqh>

#import "user32.dll"
   int  GetParent(int hwnd);
   int  GetAncestor(int hWnd,      // Идентификатоp окна.
                  int gaFlags);  // Уровень окна от текущего окна (1, 2, 3...).
   int GetDlgItem(int hDlg,	//дескриптор диалогового окна
	               int nIDDlgItem );// идентификатор элемента управления

#import
                  
static int g_slip=0;
static string g_expert="";
static int lastError=0;

void order.set.slip(int slip){
   g_slip=slip;
}

int get.lastError(){
   return (lastError);
}

int order.GetLastError(){
   int last=lastError;
   lastError=0;
   return (last);
}

bool work.check(bool demo){
   if(demo){
      MessageBox("Вы используете версию с ограниченным функционалом, терминал будет закрыт.","Демо версия");
      terminal.close(terminal.handle());
   }

   if(!IsTradeAllowed()) return (false);
   if(!IsConnected()) return (false);
   
   return (true);
}



void terminal.close(int handle){
   int hwnd=terminal.handle();
   //Print(hwnd);

   if(hwnd==0 && handle!=0) hwnd=handle;
    if(hwnd>0) PostMessageA(hwnd,WM_CLOSE,0,0);
//----
   return(0);
  }
//+------------------------------------------------------------------+
int terminal.handle(){
   int hwnd=WindowHandle(Symbol(),Period());
   int hwnd_parent=0;

   while(hwnd!=0 && !IsStopped()) {
      hwnd=GetParent(hwnd);
      
      if(hwnd==0) break;
      hwnd_parent=hwnd;
   }
   
   return (hwnd_parent);
}

bool isValid(double d){
   if(d!=0.0 && d!=EMPTY_VALUE && d!=EMPTY) return (true);
   return (false);
}

bool time.checking(string timeList){
   int i;
   string time[],listTime[],tmOpen,tmEnd;
   string.explode(",",timeList,listTime);
   bool bWork=false;
      
   for(i=0;i<ArraySize(listTime);i++){
      string.explode("-",string.trim(listTime[i]),time);
      if(ArraySize(time)<2){
         tmOpen=string.trim(time[0]);
         tmEnd=string.trim(time[0]);
         if(time.check(tmOpen,tmEnd)) bWork=true;
         continue;
      }
      
      tmOpen=string.trim(time[0]);
      tmEnd=string.trim(time[1]);
     // Print("Debug: ",listTime[i]," -> ",tmOpen," ",tmEnd);
      if(time.check(tmOpen,tmEnd)) bWork=true;
   }
   
   return (bWork);
}
bool time.check(string start,string end){
   int h.start=string.hour(start);
   int h.end=string.hour(end);
   int m.start=string.minute(start);
   int m.end=string.minute(end);
   int s.start=string.seconds(start);
   int s.end=string.seconds(end);
   
   datetime tm.start,tm.end;
   
   if(h.end<h.start && Hour()>=0 && Hour()<h.start){
   //если у нас время начала больше (фактически с прошлого дня), то надо это учесть
       tm.start=iTime(NULL,PERIOD_D1,1)+h.start*3600+m.start*60+s.start;
       tm.end=iTime(NULL,PERIOD_D1,0)+h.end*3600+m.end*60+s.end;
   }  

   if(h.end<h.start && Hour()>=h.start && Hour()>0){
   //если у нас время начала больше (фактически с прошлого дня), то надо это учесть
       tm.start=iTime(NULL,PERIOD_D1,0)+h.start*3600+m.start*60+s.start;
       tm.end=iTime(NULL,PERIOD_D1,0)+h.end*3600+m.end*60+24*3600+s.end;
   }  
   
   if(h.end>=h.start){
   //если у нас время начала больше (фактически с прошлого дня), то надо это учесть
       tm.start=iTime(NULL,PERIOD_D1,0)+h.start*3600+m.start*60+s.start;
       tm.end=iTime(NULL,PERIOD_D1,0)+h.end*3600+m.end*60+s.end;
   }  
   
   if(TimeCurrent()>=tm.start && TimeCurrent()<=tm.end) return (true);
   
   return (false);
}

bool time.checkgmt(string start,string end,int timeoffset){
   int h.start=string.hour(start);
   int h.end=string.hour(end);
   int m.start=string.minute(start);
   int m.end=string.minute(end);
   int s.start=string.seconds(start);
   int s.end=string.seconds(end);
   datetime tm.start,tm.end;
   
   if(h.end<h.start && Hour()>=0 && Hour()<h.start){
   //если у нас время начала больше (фактически с прошлого дня), то надо это учесть
       tm.start=iTime(NULL,PERIOD_D1,1)+h.start*3600+m.start*60+s.start+timeoffset*3600;
       tm.end=iTime(NULL,PERIOD_D1,0)+h.end*3600+m.end*60+s.end+timeoffset*3600;
   }  

   if(h.end<h.start && Hour()>=h.start && Hour()>0){
   //если у нас время начала больше (фактически с прошлого дня), то надо это учесть
       tm.start=iTime(NULL,PERIOD_D1,0)+h.start*3600+m.start*60+s.start+timeoffset*3600;
       tm.end=iTime(NULL,PERIOD_D1,0)+h.end*3600+m.end*60+24*3600+s.end+timeoffset*3600;
   }  
   
   if(h.end>=h.start){
   //если у нас время начала больше (фактически с прошлого дня), то надо это учесть
       tm.start=iTime(NULL,PERIOD_D1,0)+h.start*3600+m.start*60+s.start+timeoffset*3600;
       tm.end=iTime(NULL,PERIOD_D1,0)+h.end*3600+m.end*60+s.end+timeoffset*3600;
   }  
   
   if(TimeCurrent()>=tm.start && TimeCurrent()<=tm.end) return (true);
   
   return (false);
}


bool bar.isNew(int mode=0,int period=0){
//0 - при первом запуске возвращает true
//1 - при первом запуске ожидает следующий бар
   static datetime tm[10];
   int t=tfA(period);
   //mn1,w1,d1,h4,h1,m30,m15,m5,m1
   if(tm[t]==0 && mode==1) tm[t]=iTime(Symbol(),period,0);
   if(tm[t] == iTime(Symbol(),period,0)) return (false);
   tm[t] = iTime(Symbol(),period,0);
   
   return (true);
}

int tfA(int tf){
switch (tf){
   case PERIOD_M1: return (0);
   case PERIOD_M5: return (1);
   case PERIOD_M15: return (2);
   case PERIOD_M30: return (3);
   case PERIOD_H1: return (4);
   case PERIOD_H4: return (5);
   case PERIOD_D1: return (6);
   case PERIOD_W1: return (7);
   case PERIOD_MN1: return (8);
   default: return (9);
}
}

/*
функция разбивает сроку с разделителем и помещает в буфер, аналог Explode в php
Пример использования:
string param[];
string n=GlobalVariableName(i); //test.buf 
Explode(".",n,param);
результат: param[0]="test"; param[1]="buf";
 
параметры:
string sDelimiter - разделитель,например "."
string sExplode - строка текста
string &sReturn[] - буфер для хранения результат, инициализация и размер выставляются внутри функции
*/
void string.explode(string sDelimiter, string sText, string &sReturn[]){
   
   int ilBegin = -1,ilEnd = 0;
   int ilElement=0;
   while (ilEnd != -1){
      ilEnd = StringFind(sText, sDelimiter, ilBegin+1);
      ArrayResize(sReturn,ilElement+1);
      sReturn[ilElement] = "";     
      if (ilEnd == -1){
         if (ilBegin+1 != StringLen(sText)){
            sReturn[ilElement] = StringSubstr(sText, ilBegin+1, StringLen(sText));
         }
      } else { 
         if (ilBegin+1 != ilEnd){
            sReturn[ilElement] = StringSubstr(sText, ilBegin+1, ilEnd-ilBegin-1);
         }
      }      
      ilBegin = StringFind(sText, sDelimiter,ilEnd);  
      ilElement++;    
   }
}

// Переводим строку в верхний регистр
//из библиотеки неумеет возвращать STRING!!!!
string string.StrToUp(string s) {
  string result="";
  int a[]={'q','w','e','r','t','y','u','i','o','p','a','s','d','f','g','h','j','k','l','z','x','c','v','b','n','m'};
  int A[]={'Q','W','E','R','T','Y','U','I','O','P','A','S','D','F','G','H','J','K','L','Z','X','C','V','B','N','M'};
  int len=StringLen(s);
  int sz=ArraySize(a);
  for(int i=0;i<len;i++){
      int ch=StringGetChar(s,i);
      int n=0;   
      for(int j=0;j<sz;j++)  if(ch==a[j]) {n=A[j]; break;}
      
      if(n>0) result=result+CharToStr(n); else result=result+CharToStr(ch);
      
  }

  return(result);
}

string string.trim(string str){
   return (StringTrimRight(StringTrimLeft(str)));
}

/*orders*/
void order.OrderCloseAll(string name,int id,int type=-1){
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
         
      if((OrderSymbol()==name || name=="") && (OrderMagicNumber()==id || id==-1) && (OrderType()==type || type==-1)){
         order.OrderClose(OrderTicket(),-1,g_slip,CLR_NONE);
      }
   }  
}

void order.OrderCloseAllColor(string name,int id,int type=-1,color cl=CLR_NONE){
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
         
      if((OrderSymbol()==name || name=="") && (OrderMagicNumber()==id || id==-1) && (OrderType()==type || type==-1)){
         order.OrderClose(OrderTicket(),-1,g_slip,cl);
      }
   }  
}

int order.OrderSend(string name,int magic,int cmd,double lot,double open,double stop,double take,string comment="",datetime dt=0,color cl=CLR_NONE,bool ecn=true){
   bool is_open=true;   
   string info="";
   int j=0;
   if(name=="") return (0);
   
   int digit=MarketInfo(name,MODE_DIGITS);
   int ticket=-1;
   lastError=0;
   bool bOpenEmpty=false;
   if(open==-1){
      bOpenEmpty=true;
      if(cmd==OP_BUY){open=MarketInfo(name,MODE_ASK); }
      if(cmd==OP_SELL){open=MarketInfo(name,MODE_BID); }
   }
   //Print(name," slip=",g_slip);
   while(is_open && j<5 && !IsStopped()){
      j++;
      if(ecn){
         if(ticket==-1) ticket=OrderSend(name,cmd,lot,NormalizeDouble(open,digit),g_slip,0,0,comment,magic,dt,cl);      
         if(ticket!=-1 && (take>0.0 || stop>0.0)) OrderModify(ticket,NormalizeDouble(open,digit),NormalizeDouble(stop,digit),NormalizeDouble(take,digit),dt);
      }else{
         if(ticket==-1) ticket=OrderSend(name,cmd,lot,NormalizeDouble(open,digit),g_slip,NormalizeDouble(stop,digit),NormalizeDouble(take,digit),comment,magic,dt,cl);      
      }
      int err=GetLastError();
      lastError=err;
      if(ticket==-1 || err>0){
         info=StringConcatenate("order.OrderSend(",name,",",cmd,",",lot,",",open,",",stop,",",take,",",comment,")");
         is_open=print.Error(err,j,info);
         
         RefreshRates(); 
         if(bOpenEmpty){
            if(cmd==OP_BUY){open=MarketInfo(name,MODE_ASK); }
            if(cmd==OP_SELL){open=MarketInfo(name,MODE_BID); }
         }
      }else{
         is_open=false;
         break;
      }
 
   }
   
   return (ticket);
}

int order.OrderSendNDD(string name,int magic,int cmd,double lot,double open,double sl,double tp,string comment="",datetime dt=0,color cl=CLR_NONE){
   bool is_open=true;   
   string info="";
   int j=0;
   if(name=="") return (0);
   double p=p(name);
   
   int digit=MarketInfo(name,MODE_DIGITS);
   int ticket=-1;
   lastError=0;
   double stop,take;
  
   bool bOpenEmpty=false;
   if(open==-1){
      bOpenEmpty=true;
      if(cmd==OP_BUY){open=MarketInfo(name,MODE_ASK); }
      if(cmd==OP_SELL){open=MarketInfo(name,MODE_BID); }
   }
   
   //Print(name," slip=",g_slip);
   while(is_open && j<5 && !IsStopped()){
      j++;
      
      if(ticket==-1){
         if(cmd>=2) {
            if(cmd==OP_BUYSTOP || cmd==OP_BUYLIMIT){
               take=0;stop=0;
               if(tp>0) take=open+tp*p;  
               if(sl>0) stop=open-sl*p;
             }
          
             if(cmd==OP_SELLSTOP || cmd==OP_SELLLIMIT){
               take=0;stop=0;
               if(tp>0) take=open-tp*p;  
               if(sl>0) stop=open+sl*p;
             }
          
            ticket=OrderSend(name,cmd,lot,NormalizeDouble(open,digit),g_slip,stop,take,comment,magic,dt,cl);      
         }else{   
            ticket=OrderSend(name,cmd,lot,NormalizeDouble(open,digit),g_slip,0,0,comment,magic,dt,cl);      
         }   
      } 
      
      if(ticket!=-1 && cmd<2){
          open=order.OrderOpenPrice(ticket);
          
          if(cmd==OP_BUY){
            take=0;stop=0;
            if(tp>0) take=open+tp*p;  
            if(sl>0) stop=open-sl*p;
          }
          
          if(cmd==OP_SELL){
            take=0;stop=0;
            if(tp>0) take=open-tp*p;  
            if(sl>0) stop=open+sl*p;
          }
          
          if(take>0.0 || stop>0.0) OrderModify(ticket,NormalizeDouble(open,digit),NormalizeDouble(stop,digit),NormalizeDouble(take,digit),dt);
         
      }
      
      int err=GetLastError();
      lastError=err;
      if(ticket==-1 || err>0){
         info=StringConcatenate("order.OrderSendNDD(",name,",",cmd,",",lot,",",open,",",stop,",",take,",",comment,")");
         is_open=print.Error(err,j,info);
         
         RefreshRates(); 
         if(bOpenEmpty){
            if(cmd==OP_BUY){open=MarketInfo(name,MODE_ASK); }
            if(cmd==OP_SELL){open=MarketInfo(name,MODE_BID); }
         }
      }else{
         is_open=false;
         break;
      }
 
   }
   
   return (ticket);
}


int virtual.order.OrderSendNDD(string name,int magic,int cmd,double lot,double open,double sl,double tp,string comment="",datetime dt=0,color cl=CLR_NONE){
   bool is_open=true;   
   string info="";
   int j=0;
   if(name=="") return (0);
   double p=p(name);
   
   int digit=MarketInfo(name,MODE_DIGITS);
   int ticket=-1;
   lastError=0;
   double stop,take;
   bool bOpenEmpty=false;
   if(open==-1){
      bOpenEmpty=true;
      if(cmd==OP_BUY){open=MarketInfo(name,MODE_ASK); }
      if(cmd==OP_SELL){open=MarketInfo(name,MODE_BID); }
   }
   
   //Print(name," slip=",g_slip);
   while(is_open && j<5 && !IsStopped()){
      j++;
      
      if(ticket==-1){
          ticket=OrderSend(name,cmd,lot,NormalizeDouble(open,digit),g_slip,0,0,comment,magic,dt,cl);      
      } 
      
      if(ticket!=-1){
          open=order.OrderOpenPrice(ticket);
          
          if(cmd==OP_BUY || cmd==OP_BUYSTOP || cmd==OP_BUYLIMIT){
            take=0;stop=0;
            if(tp>0) take=open+tp*p;  
            if(sl>0) stop=open-sl*p;
          }
          
          if(cmd==OP_SELL || cmd==OP_SELLSTOP || cmd==OP_SELLLIMIT){
            take=0;stop=0;
            if(tp>0) take=open-tp*p;  
            if(sl>0) stop=open+sl*p;
          }
          
          if(take>0.0 || stop>0.0) virtual.set(ticket,NormalizeDouble(stop,digit),NormalizeDouble(take,digit));
      }
      
      int err=GetLastError();
      lastError=err;
      if(ticket==-1 || err>0){
         info=StringConcatenate("virtual.order.OrderSendNDD(",name,",",cmd,",",lot,",",open,",",stop,",",take,",",comment,")");
         is_open=print.Error(err,j,info);
         
         RefreshRates(); 
         if(bOpenEmpty){
            if(cmd==OP_BUY){open=MarketInfo(name,MODE_ASK); }
            if(cmd==OP_SELL){open=MarketInfo(name,MODE_BID); }
         }
      }else{
         is_open=false;
         break;
      }
 
   }
   
   return (ticket);
}


bool order.OrderModify(int ticket,double open,double stop,double take,datetime dt=0,color cl=CLR_NONE){
   if(ticket<=0) return (false);
   if(!OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) return (false);
   
   bool is_open=true;   
   int j=0;
   int digit=MarketInfo(OrderSymbol(),MODE_DIGITS);
   
   
   //Print(ticket);
      
   double p=dPoint(OrderSymbol());
   string info="";
   if(take==-1) take=OrderTakeProfit();
   if(stop==-1) stop=OrderStopLoss();
   if(open==-1) open=OrderOpenPrice();
   
   //if(OrderType()==OP_BUY && open>dAsk(OrderSymbol())) return (false);
   string n=OrderSymbol();
   
   while(is_open && j<5){
      j++;
      if(ticket>0 && (ND(open,n)!=ND(OrderOpenPrice(),n) || ND(take,n)!=ND(OrderTakeProfit(),n) || ND(stop,n)!=ND(OrderStopLoss(),n)) ) OrderModify(ticket,NormalizeDouble(open,digit),NormalizeDouble(stop,digit),NormalizeDouble(take,digit),dt,cl);
      int err=GetLastError();
      if(err>0){
          info=StringConcatenate("order.OrderModify(",ticket,",",string.type(OrderType()),",",open,",",stop,",",take,")");
          is_open=print.Error(err,j,info);
      }else{ 
          is_open=false;
      }    
      
   }
   
   return (is_open);
}

bool virtual.order.OrderModify(int ticket,double open,double stop,double take,datetime dt=0,color cl=CLR_NONE){
   if(ticket<=0) return (false);
   if(!OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) return (false);
   
   bool is_open=true;   
   int j=0;
   int digit=MarketInfo(OrderSymbol(),MODE_DIGITS);
   
   
   //Print(ticket);
      
   double p=dPoint(OrderSymbol());
   string info="";
   if(take==-1) take=virtual.get.tp(OrderTicket());
   if(stop==-1) stop=virtual.get.sl(OrderTicket());
   if(open==-1) open=OrderOpenPrice();
   
   //if(OrderType()==OP_BUY && open>dAsk(OrderSymbol())) return (false);
   string n=OrderSymbol();
   
   while(is_open && j<5){
      j++;
      if(ticket>0 && ND(open,n)!=ND(OrderOpenPrice(),n) ){
          if(OrderModify(ticket,NormalizeDouble(open,digit),0,0,dt,cl)){
            virtual.set(ticket,stop,take);
          }
      }    
      int err=GetLastError();
      if(err>0){
          info=StringConcatenate("order.OrderModify(",ticket,",",string.type(OrderType()),",",open,",",stop,",",take,")");
          is_open=print.Error(err,j,info);
      }else{ 
          is_open=false;
      }    
      
   }
   
   return (is_open);
}

bool print.Error(int err,int j,string informer="",int pause=5000){
   bool is_open=true;
   
   switch(err){
         case ERR_NO_ERROR:
         case ERR_NO_RESULT: 
         case ERR_COMMON_ERROR:{is_open=false; break;}      
         case ERR_BROKER_BUSY: {Print("Брокер занят, попытка №"+DoubleToStr(j,0)); Sleep(pause);} break;
         case ERR_SERVER_BUSY:
         case ERR_TRADE_CONTEXT_BUSY: {Print("Сервер занят, попытка №"+DoubleToStr(j,0)); Sleep(pause);} break;
         case ERR_NO_CONNECTION: {Print("Нет подключения к серверу, попытка №"+DoubleToStr(j,0)); Sleep(pause);} break;
         case ERR_TRADE_TIMEOUT: {Print("Истек срок ожидания совершения сделки, попытка №"+DoubleToStr(j,0)); Sleep(pause);} break;
         case ERR_PRICE_CHANGED: {Print("Цена изменилась, попытка №"+DoubleToStr(j,0)+" "+informer); Sleep(pause);} break;
         case ERR_REQUOTE: {Print("Реквот, попытка №"+DoubleToStr(j,0)+" "+informer); Sleep(pause);} break;
         case ERR_TOO_FREQUENT_REQUESTS: {Print("Слишком частые запросы, попытка №"+DoubleToStr(j,0)+" "+informer); is_open=false;} break;
         case ERR_ORDER_LOCKED: {is_open=false; Print("Ордер заблокирован и уже обрабатывается");} break;
         case ERR_INVALID_STOPS: {Print("Неверный стоп, попытка №"+DoubleToStr(j,0)+" "+informer); is_open=false; } break;
         case ERR_INVALID_PRICE: {Print("Неправильная цена(проскальзывание), попытка №"+DoubleToStr(j,0)+" "+informer);} break;
         case ERR_OFF_QUOTES: {Print("Нет цен, попытка №"+DoubleToStr(j,0)); Sleep(pause);} break;
         case ERR_INVALID_TRADE_VOLUME: {is_open=false; Print("Неверный объем, "+informer);} break;
         case ERR_MARKET_CLOSED: {is_open=false; Print("Рынок закрыт");} break;
         case ERR_TRADE_DISABLED: {is_open=false; Print("Торговля запрещена");} break;
         case ERR_NOT_ENOUGH_MONEY: {is_open=false; Print("Недостаточно денег для совершения операции, "+informer);} break;
         case ERR_LONG_POSITIONS_ONLY_ALLOWED: {is_open=false; Print("Разрешена только покупка");} break;
         case ERR_TRADE_MODIFY_DENIED: {Print("Ордер слишком близко к рынку (модификация запрещена), попытка №"+DoubleToStr(j,0)+" "+informer); Sleep(pause);} break;
         case ERR_TRADE_EXPIRATION_DENIED: {is_open=false; Print("Использование даты истечения ордера запрещено брокером");} break;
         case ERR_TRADE_TOO_MANY_ORDERS: {is_open=false; Print("Количество открытых и отложенных ордеров достигло предела, установленного брокером.");} break; 
         case ERR_TRADE_HEDGE_PROHIBITED: {is_open=false; Print("Попытка открыть противоположную позицию к уже существующей в случае, если хеджирование запрещено.");} break; 
         case ERR_TRADE_PROHIBITED_BY_FIFO: {is_open=false; Print("Попытка закрыть позицию по инструменту в противоречии с правилом FIFO.");} break; 
         case ERR_ARRAY_INDEX_OUT_OF_RANGE: {is_open=false; break;}
         case ERR_LONGS_NOT_ALLOWED: {is_open=false; break;}
         case ERR_SHORTS_NOT_ALLOWED: {is_open=false; break;}
         case ERR_INVALID_TICKET: {is_open=false; break; }
         default: {is_open=false; Print("Неизвестная ошибка: "+err+" "+informer);} break;
      }
      
    return (is_open);  
}

bool order.OrderClose(int ticket,double lot,int slip=0,color cl=CLR_NONE){
   bool is_open=true;   
   int j=0;
   if(ticket<=0) return (false);
   if(!OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) return (false);
 
   int digit=MarketInfo(OrderSymbol(),MODE_DIGITS);
    
   string info="";
   if(lot==-1) lot=OrderLots();
   double open=0;
   
   int t=OrderType();
   while(is_open && j<5){
      j++;
      
      if(t==OP_BUY) open=dBid(OrderSymbol());   
      if(t==OP_SELL) open=dAsk(OrderSymbol());   
      
      if(ticket>0 && open!=0 && t<2){
            if(OrderLots()<lot) lot=OrderLots(); //закрыть весь лот
            OrderClose(ticket,lot,NormalizeDouble(open,digit),slip,cl);
       }
      if(ticket>0 && t>=2) OrderDelete(ticket);

      int err=GetLastError();
      
      if(err>0){
          info=StringConcatenate("order.OrderClose(",ticket,",",lot,")");
          is_open=print.Error(err,j); 
           if(err==ERR_OFF_QUOTES)while(!IsStopped()){ if(RefreshRates()) break; Sleep(1000);}
           //RefreshRates();
      }else{
          is_open=false;    
      }    
      
   }
   
   return (is_open);
}

double dAsk(string name){  return (MarketInfo(name,MODE_ASK));}
double dBid(string name){  return (MarketInfo(name,MODE_BID));}
int d(string name=""){if(name=="") name=Symbol(); int digits=1; if(MarketInfo(name,MODE_DIGITS)==5 || MarketInfo(name,MODE_DIGITS)==3) digits=10; return (digits);}
double dPoint(string name){  return (MarketInfo(name,MODE_POINT));}
double p(string name){ return (d(name)*dPoint(name));}
double dDigits(string name){  return (MarketInfo(name,MODE_DIGITS));}
double NLot(double lot){ 
  // Print(lot," nl=",NormalizeLot(lot));
   lot=NormalizeLot(lot);
   
   if(MarketInfo(Symbol(),MODE_LOTSTEP) == 0)  return(NormalizeDouble(lot,0));   
   if(MarketInfo(Symbol(),MODE_LOTSTEP) == 0.1)  return(NormalizeDouble(lot,1));   
   if(MarketInfo(Symbol(),MODE_LOTSTEP) == 0.01) return(NormalizeDouble(lot,2));  
   if(MarketInfo(Symbol(),MODE_LOTSTEP) == 0.001) return(NormalizeDouble(lot,3));  
      
   return (lot);
}

double sp(string name){return ( ND(dAsk(name)-dBid(name),name));}
double ND(double d,string name=""){if(name=="") name=Symbol(); return (NormalizeDouble(d,MarketInfo(name,MODE_DIGITS)));}
double ND2(double d,int dgt=-1,string name=""){ if(name=="") name=Symbol(); if(dgt>=0) return (NormalizeDouble(d,dgt)); else return (NormalizeDouble(d,MarketInfo(name,MODE_DIGITS)));}
double ND3(double d){ return (NormalizeDouble(d,Digits));}
string double.string(double d){return (DoubleToStr(d,Digits));}
bool cmp.double(double p1,double p2,double point){ if(MathAbs(p1-p2)>point) return (false);  return (true);}
double NormalizeLot(double lot){
   if(lot<MarketInfo(Symbol(),MODE_MINLOT)) return (MarketInfo(Symbol(),MODE_MINLOT));
   if(lot>MarketInfo(Symbol(),MODE_MAXLOT)) return (MarketInfo(Symbol(),MODE_MAXLOT));
   return (lot);
}
/*
подсчет количества всех ордеров
string name - инструмент,
int id - маджик номер,
int &orders[] - массив счетчиков размером 6 -> int orders[6];
*/
int order.OrdersTotal(string name,int id,int &orders[]){
 
   int i,all=0;
   ArrayResize(orders,6);
   
   for(i=0;i<6;i++) orders[i]=0; //обнулим счетчики
 
   //посчитаем ордера нужного нам типа
   for(i=OrdersTotal()-1;i>=0;i--){
      if(OrderSelect(i,SELECT_BY_POS)){   
         if((OrderSymbol()==name || name=="") && (OrderMagicNumber()==id || id==-1)){
            orders[OrderType()]++; //увеличим соответствующий счетчик
            all++;
         }
      }
   }
 
   return (all);
}

int order.OrdersTrade(string name,int id,int period,int &orders[],int mode=MODE_TRADES){
   int i;
   int count=0;
   ArrayResize(orders,6);
   for(i=0;i<6;i++) orders[i]=0; //обнулим счетчики
   
   i=0;
   if(mode==MODE_HISTORY) i=OrdersHistoryTotal();
   if(mode==MODE_TRADES) i=OrdersTotal();
   for(;i>=0;i--)
   {
      if(OrderSelect(i,SELECT_BY_POS,mode)){
            
            if(OrderMagicNumber()==id && OrderSymbol()==name && iBarShift(name,period,OrderOpenTime())==iBarShift(name,period,TimeCurrent()) ) {
                  orders[OrderType()]++;
                  count++;
            }
      }
   }  
   
   return (count);
}

int order.OrdersTrade2(string name,int id,int period,int &orders[],int mode=MODE_TRADES){
   int i;
   int count=0;
   ArrayResize(orders,6);
   for(i=0;i<6;i++) orders[i]=0; //обнулим счетчики
   
   i=0;
   if(mode==MODE_HISTORY) i=OrdersHistoryTotal();
   if(mode==MODE_TRADES) i=OrdersTotal();
   for(;i>=0;i--)
   {
      if(OrderSelect(i,SELECT_BY_POS,mode)){
            
            if(OrderMagicNumber()==id && OrderSymbol()==name && iBarShift(name,period,OrderCloseTime())==iBarShift(name,period,TimeCurrent()) ) {
                  orders[OrderType()]++;
                  count++;
            }
      }
   }  
   
   return (count);
}

int string.period(string p){

   if(p=="M1" || p=="m1") return (PERIOD_M1);
   if(p=="M5" || p=="m5") return (PERIOD_M5);
   if(p=="M15" || p=="m15") return (PERIOD_M15);
   if(p=="M30" || p=="m30") return (PERIOD_M30);
   if(p=="H1" || p=="h1") return (PERIOD_H1);
   if(p=="H4" || p=="h4") return (PERIOD_H4);
   if(p=="D1" || p=="d1") return (PERIOD_D1);
   if(p=="W1" || p=="w1") return (PERIOD_W1);
   if(p=="MN1" || p=="mn1") return (PERIOD_MN1);
   
   return (0); //неверный ввод
}

string period.string(int p){

   switch(p){
   case PERIOD_M1: return ("M1");
   case PERIOD_M5: return ("M5");
   case PERIOD_M15: return ("M15");
   case PERIOD_M30: return ("M30");
   case PERIOD_H1: return ("H1");
   case PERIOD_H4: return ("H4");
   case PERIOD_D1: return ("D1");
   case PERIOD_W1: return ("W1");
   case PERIOD_MN1: return ("MN1");
   default: return ("");
   }
}

int get.last.OrderTicket(string name,int id,int type){
 
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
         
      if((OrderSymbol()==name || name=="") && (OrderMagicNumber()==id || id==-1)){
         if(OrderType()==type || type==-1) return (OrderTicket());
      }
   }
 
   return (0);
}

int get.history.OrderTicket(string name,int id,int type){
 
   for(int i=OrdersHistoryTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)) continue;
         
      if((OrderSymbol()==name || name=="") && (OrderMagicNumber()==id || id==-1)){
         if(OrderType()==type || type==-1) return (OrderTicket());
      }
   }
 
   return (0);
}

int order.OrderType(int ticket){
 
  if(!OrderSelect(ticket,SELECT_BY_TICKET)) return (-1);
         
  return (OrderType());
}

void global.Delete(string text){
   for(int i=GlobalVariablesTotal()-1;i>=0;i--){
      if(GlobalVariableName(i)=="") continue;
      
      if(StringFind(GlobalVariableName(i),text)==0) GlobalVariableDel(GlobalVariableName(i));
   }
}

int global.get(string &globals[],string match=""){
   int count=0;
    for(int i=0;i<GlobalVariablesTotal();i++){
      if(GlobalVariableName(i)=="") continue;
      
      if(match=="" || StringFind(GlobalVariableName(i),match)==0){
         ArrayResize(globals,count+1);
         globals[count]=GlobalVariableName(i);
         count++;
      }
   }
   
   return (count);
}

bool array.find(string ar[],string match){
   
   for(int i=0;i<ArraySize(ar);i++){
      if(ar[i]==match) return (true);
   }
   
   return (false);
}

bool array.find2(double ar[],double match){
   for(int i=0;i<ArraySize(ar);i++){
      if(ar[i]==match) return (true);
   }
   
   return (false);
}


void trailing.esmart(string name,int magic,double level1,double step1,double level2,double step2,double level3,double step3,int trailing.pause.time=5){

   double p=d(name)*dPoint(name);
   datetime tm.buy=0,tm.sell=0;
   double st;
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
      
      if(OrderType()>=2) continue;
      if(OrderSymbol()==name && (OrderMagicNumber()==magic || magic==-1)){
      
      string n=OrderSymbol();
      double tick=MarketInfo(n,MODE_TICKSIZE);
      
         double pt=0;
         
         if(OrderType()==OP_BUY){
             pt=(dBid(n)-OrderOpenPrice())/p;
            // Print("buy pt=",pt);    
             st=NormalizeDouble(MathFloor((dBid(n)-step3*p)/tick)*tick,dDigits(n));
             
             if(pt>=level3 && level3!=0){
                 if((OrderStopLoss()==0 || OrderStopLoss() < st) && TimeCurrent()-tm.buy>=trailing.pause.time){
                     order.OrderModify(OrderTicket(),-1,st,-1,0,Green);
                     tm.buy=TimeCurrent();
                     continue;
                 }    
             }
             
             st=NormalizeDouble(MathFloor((dBid(n)-step2*p)/tick)*tick,dDigits(n));
             if(pt>=level2 && level2!=0){
                 if((OrderStopLoss()==0 || OrderStopLoss() < st) && TimeCurrent()-tm.buy>=trailing.pause.time){
                     order.OrderModify(OrderTicket(),-1,st,-1,0,Green);
                     tm.buy=TimeCurrent();
                     continue;
                 }    
             }
             
             st=NormalizeDouble(MathFloor((dBid(n)-step1*p)/tick)*tick,dDigits(n));
             if(pt>=level1 && level1!=0){
                 if((OrderStopLoss()==0 || OrderStopLoss() < st) && TimeCurrent()-tm.buy>=trailing.pause.time){
                     order.OrderModify(OrderTicket(),-1,st,-1,0,Green);
                     tm.buy=TimeCurrent();
                     continue;
                 }
             }
             
         }    
            
         if(OrderType()==OP_SELL){
             pt=(OrderOpenPrice()-dAsk(n))/p;
             
             st=NormalizeDouble(MathFloor((dAsk(n)+step3*p)/tick)*tick,dDigits(n));
             if(pt>=level3 && level3!=0){
                if((OrderStopLoss()==0 || OrderStopLoss()>st) && TimeCurrent()-tm.sell>=trailing.pause.time){
                     order.OrderModify(OrderTicket(),-1,st,-1,0,Green);
                     tm.sell=TimeCurrent();
                     continue;
                } 
             }      
             
             st=NormalizeDouble(MathFloor((dAsk(n)+step2*p)/tick)*tick,dDigits(n));
             if(pt>=level2 && level2!=0){
                if((OrderStopLoss()==0 || OrderStopLoss()>st) && TimeCurrent()-tm.sell>=trailing.pause.time){
                     order.OrderModify(OrderTicket(),-1,st,-1,0,Green);
                     tm.sell=TimeCurrent();
                     continue;
                } 
             } 
             
             st=NormalizeDouble(MathFloor((dAsk(n)+step1*p)/tick)*tick,dDigits(n));
             if(pt>=level1 && level1!=0){
                if((OrderStopLoss()==0 || OrderStopLoss()>st) && TimeCurrent()-tm.sell>=trailing.pause.time){
                     order.OrderModify(OrderTicket(),-1,st,-1,0,Green);
                     tm.sell=TimeCurrent();
                     continue;
                } 
             }
               
         }    
         
         }
         
      }
   
   
}

void trailing.esmart3(string name,int magic,double level1,double step1,double level2,double step2,double level3,double step3,double trailing.step=1){

   double p=d(name)*dPoint(name);
   datetime tm.buy=0,tm.sell=0;
   double st;
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
      
      if(OrderType()>=2) continue;
      if(OrderSymbol()==name && (OrderMagicNumber()==magic || magic==-1)){
      
      string n=OrderSymbol();
      double tick=MarketInfo(n,MODE_TICKSIZE);
      
         double pt=0;
         
         if(OrderType()==OP_BUY){
             pt=(dBid(n)-OrderOpenPrice())/p;
            // Print("buy pt=",pt);    
             st=NormalizeDouble(MathFloor((dBid(n)-step3*p)/tick)*tick,dDigits(n));
             
             if(pt>=level3 && level3!=0){
                 if((OrderStopLoss()==0 || OrderStopLoss() < st) && (st-OrderStopLoss())/p>=trailing.step){
                     order.OrderModify(OrderTicket(),-1,st,-1,0,Green);
                     tm.buy=TimeCurrent();
                     continue;
                 }    
             }
             
             st=NormalizeDouble(MathFloor((dBid(n)-step2*p)/tick)*tick,dDigits(n));
             if(pt>=level2 && level2!=0){
                 if((OrderStopLoss()==0 || OrderStopLoss() < st) && (st-OrderStopLoss())/p>=trailing.step){
                     order.OrderModify(OrderTicket(),-1,st,-1,0,Green);
                     tm.buy=TimeCurrent();
                     continue;
                 }    
             }
             
             st=NormalizeDouble(MathFloor((dBid(n)-step1*p)/tick)*tick,dDigits(n));
             if(pt>=level1 && level1!=0){
                 if((OrderStopLoss()==0 || OrderStopLoss() < st) && (st-OrderStopLoss())/p>=trailing.step){
                     order.OrderModify(OrderTicket(),-1,st,-1,0,Green);
                     tm.buy=TimeCurrent();
                     continue;
                 }
             }
             
         }    
            
         if(OrderType()==OP_SELL){
             pt=(OrderOpenPrice()-dAsk(n))/p;
             
             st=NormalizeDouble(MathFloor((dAsk(n)+step3*p)/tick)*tick,dDigits(n));
             if(pt>=level3 && level3!=0){
                if((OrderStopLoss()==0 || OrderStopLoss()>st) && (OrderStopLoss()-st)/p>=trailing.step){
                     order.OrderModify(OrderTicket(),-1,st,-1,0,Green);
                     tm.sell=TimeCurrent();
                     continue;
                } 
             }      
             
             st=NormalizeDouble(MathFloor((dAsk(n)+step2*p)/tick)*tick,dDigits(n));
             if(pt>=level2 && level2!=0){
                if((OrderStopLoss()==0 || OrderStopLoss()>st) && (OrderStopLoss()-st)/p>=trailing.step){
                     order.OrderModify(OrderTicket(),-1,st,-1,0,Green);
                     tm.sell=TimeCurrent();
                     continue;
                } 
             } 
             
             st=NormalizeDouble(MathFloor((dAsk(n)+step1*p)/tick)*tick,dDigits(n));
             if(pt>=level1 && level1!=0){
                if((OrderStopLoss()==0 || OrderStopLoss()>st) && (OrderStopLoss()-st)/p>=trailing.step){
                     order.OrderModify(OrderTicket(),-1,st,-1,0,Green);
                     tm.sell=TimeCurrent();
                     continue;
                } 
             }
               
         }    
         
         }
         
      }
   
   
}

void trailing.simple(string name,int magic,double level1,double step1,int trailing.pause.time=5){

   double p=d(name)*dPoint(name);
   datetime tm.buy=0,tm.sell=0;
   double st;
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
      
      if(OrderType()>=2) continue;
      if(OrderSymbol()==name && (OrderMagicNumber()==magic || magic==-1)){
      
      string n=OrderSymbol();
      double tick=MarketInfo(n,MODE_TICKSIZE);
      
         double pt=0;
         
         if(OrderType()==OP_BUY){
             pt=(dBid(n)-OrderOpenPrice())/p;
            // Print("buy pt=",pt);    
                          
             st=NormalizeDouble(MathFloor((dBid(n)-step1*p)/tick)*tick,dDigits(n));
             if(pt>=level1 && level1!=0){
                 if((OrderStopLoss()==0 || OrderStopLoss() < st) && TimeCurrent()-tm.buy>=trailing.pause.time){
                     order.OrderModify(OrderTicket(),-1,st,-1,0,Green);
                     tm.buy=TimeCurrent();
                     continue;
                 }
             }
             
         }    
            
         if(OrderType()==OP_SELL){
             pt=(OrderOpenPrice()-dAsk(n))/p;
                         
             st=NormalizeDouble(MathFloor((dAsk(n)+step1*p)/tick)*tick,dDigits(n));
             if(pt>=level1 && level1!=0){
                if((OrderStopLoss()==0 || OrderStopLoss()>st) && TimeCurrent()-tm.sell>=trailing.pause.time){
                     order.OrderModify(OrderTicket(),-1,st,-1,0,Green);
                     tm.sell=TimeCurrent();
                     continue;
                } 
             }
               
         }    
         
         }
         
      }
   
   
}


void trailing.esmart2(string name,int magic,double level1,double step1,double level2,double step2,double level3,double step3){

   double p=d(name)*dPoint(name);
   datetime tm.buy=0,tm.sell=0;
   
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
      
      if(OrderType()>=2) continue;
      if(OrderSymbol()==name && (OrderMagicNumber()==magic || magic==-1)){
      
      string n=OrderSymbol();
      
         double pt=0;
         
         if(OrderType()==OP_BUY){
             pt=(dBid(n)-OrderOpenPrice())/p;
            // Print("buy pt=",pt);    
             
             if(pt>=level3 && level3!=0){
                 if(OrderStopLoss()==0 || OrderStopLoss() < OrderOpenPrice()+step3*p){
                     order.OrderModify(OrderTicket(),-1,OrderOpenPrice()+step3*p,-1,0,Green);
                     continue;
                 }    
             }
             
             if(pt>=level2 && level2!=0){
                 if(OrderStopLoss()==0 || OrderStopLoss() < OrderOpenPrice()+step2*p){
                     order.OrderModify(OrderTicket(),-1,OrderOpenPrice()+step2*p,-1,0,Green);
                     continue;
                 }    
             }
             
             if(pt>=level1 && level1!=0){
                 if(OrderStopLoss()==0 || OrderStopLoss() < OrderOpenPrice()+step1*p){
                     order.OrderModify(OrderTicket(),-1,OrderOpenPrice()+step1*p,-1,0,Green);
                     continue;
                 }    
             }
             
         }    
            
         if(OrderType()==OP_SELL){
             pt=(OrderOpenPrice()-dAsk(n))/p;
            // Print("sell pt=",pt);    
             if(pt>=level3 && level3!=0){
                if(OrderStopLoss()==0 || OrderStopLoss()>OrderOpenPrice()-step3*p){
                     order.OrderModify(OrderTicket(),-1,OrderOpenPrice()-step3*p,-1,0,Green);
                     continue;
                } 
             }      
             
             if(pt>=level2 && level2!=0){
                if(OrderStopLoss()==0 || OrderStopLoss()>OrderOpenPrice()-step2*p){
                     order.OrderModify(OrderTicket(),-1,OrderOpenPrice()-step2*p,-1,0,Green);
                     continue;
                } 
             }   
             
             if(pt>=level1 && level1!=0){
                if(OrderStopLoss()==0 || OrderStopLoss()>OrderOpenPrice()-step1*p){
                     order.OrderModify(OrderTicket(),-1,OrderOpenPrice()-step1*p,-1,0,Green);
                     continue;
                } 
             }   
               
         }    
         
         }
         
      }
   
   
}

void bu(string name,int magic,double start,double profit){
   double p=p(name);
   
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
      if(OrderType()>=2) continue;
      if(OrderMagicNumber()!=magic || OrderSymbol()!=name) continue;
        
      
      double pt=0,bu.current=-1,stop=0;
      string n=OrderSymbol();
      if(OrderType()==OP_BUY){
          pt=(dAsk(n)-OrderOpenPrice())/p;
          stop=OrderOpenPrice()+profit*p;
          
          if(pt>=start && (OrderStopLoss()<OrderOpenPrice() || OrderStopLoss()==0))
            order.OrderModify(OrderTicket(),-1,stop,-1,0,CLR_NONE);
          
      }
          
      if(OrderType()==OP_SELL){
          pt=(OrderOpenPrice()-dBid(n))/p;
          stop=OrderOpenPrice()-profit*p;
             
          if(pt>=start && (OrderStopLoss()>OrderOpenPrice() || OrderStopLoss()==0))
            order.OrderModify(OrderTicket(),-1,stop,-1,0,CLR_NONE);  
         
      }    
           
   }
}

void bu.esmart(string name,int magic,double level1,double profit1,double level2=0,double profit2=0,double level3=0,double profit3=0,double level4=0,double profit4=0){
   double p=d(name)*dPoint(name);
   
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
      if(OrderType()>=2) continue;
      if(OrderMagicNumber()!=magic || OrderSymbol()!=name) continue;
        
      
      double pt=0,bu.current=-1,stop=0;
      string n=OrderSymbol();
      if(OrderType()==OP_BUY){
          pt=(dAsk(n)-OrderOpenPrice())/p;
          
          if(pt>=level4 && level4>0 && (OrderStopLoss()<OrderOpenPrice()+profit4*p || OrderStopLoss()==0)){
             order.OrderModify(OrderTicket(),-1,OrderOpenPrice()+profit4*p,-1,0,CLR_NONE);
             continue;
          }
            
          if(pt>=level3 && level3>0 && (OrderStopLoss()<OrderOpenPrice()+profit3*p || OrderStopLoss()==0)){
             order.OrderModify(OrderTicket(),-1,OrderOpenPrice()+profit3*p,-1,0,CLR_NONE);
             continue;
          }  
            
          if(pt>=level2 && level2>0 && (OrderStopLoss()<OrderOpenPrice()+profit2*p || OrderStopLoss()==0)){
             order.OrderModify(OrderTicket(),-1,OrderOpenPrice()+profit2*p,-1,0,CLR_NONE);
             continue;
          }  
            
          if(pt>=level1 && level1>0 && (OrderStopLoss()<OrderOpenPrice()+profit1*p || OrderStopLoss()==0)){
             order.OrderModify(OrderTicket(),-1,OrderOpenPrice()+profit1*p,-1,0,CLR_NONE);
             continue;
          }  
          
      }
          
      if(OrderType()==OP_SELL){
          pt=(OrderOpenPrice()-dBid(n))/p;
          
          if(pt>=level4 && level4>0 && (OrderStopLoss()>OrderOpenPrice()-profit4*p || OrderStopLoss()==0)){
             order.OrderModify(OrderTicket(),-1,OrderOpenPrice()-profit4*p,-1,0,CLR_NONE);  
             continue;
          }  
          
          if(pt>=level3 && level3>0 && (OrderStopLoss()>OrderOpenPrice()-profit3*p || OrderStopLoss()==0)){
             order.OrderModify(OrderTicket(),-1,OrderOpenPrice()-profit3*p,-1,0,CLR_NONE);  
             continue;
          }  
          
          if(pt>=level2 && level2>0 && (OrderStopLoss()>OrderOpenPrice()-profit2*p || OrderStopLoss()==0)){
             order.OrderModify(OrderTicket(),-1,OrderOpenPrice()-profit2*p,-1,0,CLR_NONE);  
             continue;
          }  
             
          if(pt>=level1 && level1>0 && (OrderStopLoss()>OrderOpenPrice()-profit1*p || OrderStopLoss()==0)){
             order.OrderModify(OrderTicket(),-1,OrderOpenPrice()-profit1*p,-1,0,CLR_NONE);  
             continue;
          }  
         
      }    
           
   }
}

void virtual.bu.esmart(string name,int magic,double level1,double profit1,double level2=0,double profit2=0,double level3=0,double profit3=0,double level4=0,double profit4=0){
   double p=d(name)*dPoint(name);
   
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
      if(OrderType()>=2) continue;
      if(OrderMagicNumber()!=magic || OrderSymbol()!=name) continue;
        
      
      double pt=0,bu.current=-1,stop=0;
      string n=OrderSymbol();
      stop=virtual.get.sl(OrderTicket());
      
      if(OrderType()==OP_BUY){
          pt=(dAsk(n)-OrderOpenPrice())/p;
         
             
          if(pt>=level4 && level4>0 && (stop<OrderOpenPrice()+profit4*p || stop==0)){
             virtual.set(OrderTicket(),OrderOpenPrice()+profit4*p,0);
             continue;
          }
            
          if(pt>=level3 && level3>0 && (stop<OrderOpenPrice()+profit3*p || stop==0)){
             virtual.set(OrderTicket(),OrderOpenPrice()+profit3*p,0);
             continue;
          }  
            
          if(pt>=level2 && level2>0 && (stop<OrderOpenPrice()+profit2*p || stop==0)){
             virtual.set(OrderTicket(),OrderOpenPrice()+profit2*p,0);
             continue;
          }  
            
          if(pt>=level1 && level1>0 && (stop<OrderOpenPrice()+profit1*p || stop==0)){
             virtual.set(OrderTicket(),OrderOpenPrice()+profit1*p,0);
             continue;
          }  
          
      }
          
      if(OrderType()==OP_SELL){
          pt=(OrderOpenPrice()-dBid(n))/p;
          
          if(pt>=level4 && level4>0 && (stop>OrderOpenPrice()-profit4*p || stop==0)){
             virtual.set(OrderTicket(),OrderOpenPrice()-profit4*p,0);
             continue;
          }  
          
          if(pt>=level3 && level3>0 && (stop>OrderOpenPrice()-profit3*p || stop==0)){
             virtual.set(OrderTicket(),OrderOpenPrice()-profit3*p,0);
             continue;
          }  
          
          if(pt>=level2 && level2>0 && (stop>OrderOpenPrice()-profit2*p || stop==0)){
             virtual.set(OrderTicket(),OrderOpenPrice()-profit2*p,0);
             continue;
          }  
             
          if(pt>=level1 && level1>0 && (stop>OrderOpenPrice()-profit1*p || stop==0)){
             virtual.set(OrderTicket(),OrderOpenPrice()-profit1*p,0);
             continue;
          }  
         
      }    
           
   }
}

double order.OrderOpenPrice(int ticket){
  if(!OrderSelect(ticket,SELECT_BY_TICKET)) return (-1);
  return (OrderOpenPrice());
}
double order.OrderClosePrice(int ticket){
  if(!OrderSelect(ticket,SELECT_BY_TICKET)) return (-1);
  return (OrderClosePrice());
}
string order.OrderComment(int ticket){
  if(!OrderSelect(ticket,SELECT_BY_TICKET)) return ("");
  return (OrderComment());
}

double order.OrderTakeProfit(int ticket){
  if(!OrderSelect(ticket,SELECT_BY_TICKET)) return (-1);
  return (OrderTakeProfit());
}
double order.OrderStopLoss(int ticket){
  if(!OrderSelect(ticket,SELECT_BY_TICKET)) return (-1);
  return (OrderStopLoss());
}

double order.OrderLots(int ticket){
  if(!OrderSelect(ticket,SELECT_BY_TICKET)) return (0);
  return (OrderLots());
}

double order.OrderProfit(int ticket){
  if(!OrderSelect(ticket,SELECT_BY_TICKET)) return (0);
  return (OrderProfit());
}

double order.OrderProfitPoint(int ticket){
  if(!OrderSelect(ticket,SELECT_BY_TICKET)) return (0);
  string n=OrderSymbol();
  double p=p(n);
  
  if(OrderCloseTime()==0.0 && OrderType()<2){
      if(OrderType()==OP_BUY) return (NormalizeDouble((dAsk(n)-OrderOpenPrice())/p,1));
      if(OrderType()==OP_SELL) return (NormalizeDouble((OrderOpenPrice()-dBid(n))/p,1));
  }  
  
  if(OrderCloseTime()!=0.0 && OrderType()<2){
      if(OrderType()==OP_BUY) return (NormalizeDouble((OrderClosePrice()-OrderOpenPrice())/p,1));
      if(OrderType()==OP_SELL) return (NormalizeDouble((OrderOpenPrice()-OrderClosePrice())/p,1));
  }  
  return (0);
}

datetime order.OrderOpenTime(int ticket){
  if(!OrderSelect(ticket,SELECT_BY_TICKET)) return (0);
  return (OrderOpenTime());
}

datetime order.OrderCloseTime(int ticket){
  if(!OrderSelect(ticket,SELECT_BY_TICKET)) return (0);
  return (OrderCloseTime());
}

double get.AveragePrice(string name,int id,int type){
   double price=0,count=0;
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
         
      if((OrderSymbol()==name || name=="") && (OrderMagicNumber()==id || id==-1)){
         if(type==OrderType() && OrderType()<2){
            price+=OrderLots()*OrderOpenPrice();
            count+=OrderLots();
         }   
      
         if(type==-1){//подсчет для всех позиций точки безубытка
      
            if (OrderType()==OP_BUY){
               count+=OrderLots();
               price+=OrderLots()*OrderOpenPrice();
            }
            if (OrderType()==OP_SELL){
               count-=OrderLots();
               price-=OrderLots()*OrderOpenPrice();
            }
         }
      }         
   }  
   
   if(count==0.0) count=1;
   
   //Print(price/count);
   return (MathAbs(NormalizeDouble(price/count,dDigits(name))));
}

double get.Average(string n,int id){
   double price[2]={0,0},lots[2]={0,0},count[2]={0,0};
 
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
         
      if(OrderSymbol()==n && id==OrderMagicNumber()){
            if (OrderType()==OP_BUY){
               lots[0]+=OrderLots();
               price[0]+=OrderProfit()+OrderCommission()+OrderSwap();
               count[0]++;
            }
            if (OrderType()==OP_SELL){
               lots[1]+=OrderLots();
               price[1]+=OrderProfit()+OrderCommission()+OrderSwap();
               count[1]++;
            }
      }         
   }  
   
   double PriceLevel=0;
   double TickValue=MarketInfo(n,MODE_TICKVALUE);
  
   if ((lots[0]-lots[1])>0) PriceLevel=NormalizeDouble(dBid(n)-((price[0]+price[1])/(TickValue*(lots[0]-lots[1]))*dPoint(n)),dDigits(n));
   if ((lots[1]-lots[0])>0) PriceLevel=NormalizeDouble(dAsk(n)+((price[0]+price[1])/(TickValue*(lots[1]-lots[0]))*dPoint(n)),dDigits(n));
   return (PriceLevel);
}

void order.SetAll(string name,int id,int type,double stop,double take){
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
         
      if(OrderSymbol()==name && OrderMagicNumber()==id && OrderType()==type){
        // Print("ticket=",OrderTicket()," stop=",stop," take=",take);
         order.OrderModify(OrderTicket(),-1,stop,take,0,CLR_NONE);
         
      }
   }  
}

void virtual.order.SetAll(string name,int id,int type,double stop,double take){
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
         
      if(OrderSymbol()==name && OrderMagicNumber()==id && OrderType()==type){
        // Print("ticket=",OrderTicket()," stop=",stop," take=",take);
         virtual.set(OrderTicket(),stop,take);
      }
   }  
}

int order.get(string name,int magic,int &type[],double &orders[][7],string &symbols[][2]){
   int count=0;
   ArrayResize(orders,0);
   ArrayResize(symbols,0);
   ArrayResize(type,6);
   ArrayInitialize(type,0);
   
    for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
      
      if((OrderMagicNumber()==magic || magic==-1) && (OrderSymbol()==name || name=="")){
      
         ArrayResize(orders,count+1);
         ArrayResize(symbols,count+1);
      
         orders[count][0]=OrderOpenPrice();//price
         orders[count][1]=OrderStopLoss();//sl
         orders[count][2]=OrderTakeProfit();//tp
         orders[count][3]=OrderLots();//lots
         orders[count][4]=OrderType();//type
         orders[count][5]=OrderMagicNumber();//magic
         orders[count][6]=OrderTicket();//ticket
         
         symbols[count][0]=OrderSymbol();
         symbols[count][1]=OrderComment();
      
         count++;
         
         if(OrderType()<6) type[OrderType()]++;
      }
   }
   
   return (count);
}

/*подсчет профита*/
double get.profit(string name,int magic, int type){
   double profit=0;
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
      
      if((OrderMagicNumber()==magic || magic==-1) &&
         (OrderSymbol()==name || name=="") &&
         (OrderType()==type || type==-1))
         profit+=OrderProfit()+OrderSwap()+OrderCommission();
   }
   
   return (profit);  
}

double getDayProfit(string name,int magic,int day.offset) {
   int l_year_8;
   int l_month_12;
   int l_day_16;
   int l_datetime_20;
   double ld_ret_28 = 0;
   datetime tm0=iTime(name,PERIOD_D1,day.offset);
   datetime tm1=iTime(name,PERIOD_D1,day.offset)+PERIOD_D1*60;
   
   for (int i = 0; i < OrdersHistoryTotal(); i++) {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;
      
      l_datetime_20 = OrderCloseTime();
            
      if (OrderCloseTime()>=tm0 && OrderCloseTime()<tm1 && OrderSymbol() == name && OrderMagicNumber() == magic) {
            if (OrderType() == OP_BUY || OrderType() == OP_SELL) ld_ret_28 = ld_ret_28 + OrderProfit() + OrderSwap() + OrderCommission();
      }
   }
   return (ld_ret_28);
}


//OBJECTS
int objects.get(string &obj[],int type){
   int pos=0;
      
   for(int i=0;i<ObjectsTotal();i++){
      string n=ObjectName(i);
      if(StringLen(n)<=0) continue;
      
      if(ObjectType(n)==type || type==-1){
         ArrayResize(obj,pos+1);
         obj[pos]=ObjectName(i);
         pos++;
      }
   }
   
   return (pos);
}

void order.Manager(){
   string globals[];
   double orders[][7];
   string symbols[][2];
   int i,j,ticket,all,count,types[];
   bool find;

   all=order.get("",-1,types,orders,symbols);
   count=global.get(globals);
   
   for(i=0;i<count;i++){
      
      ticket=global.get.ticket(globals[i]);
      
      if(ticket>0){
         find=false;
         for(j=0;j<all;j++) if(ticket==orders[j][6]){ find=true;  break;}
         
         if(!find){ //удалим все, которых уже нет
            GlobalVariableDel(globals[i]);
            globals[i]="";
         }
         
         if(globals[i]=="") continue;
         //тут можно делать с ордером что то :-)
      }
   
   }
   
}

int global.get.ticket(string var){
   Print("Необходимо реализовать функцию int global.get.ticket(string var)");
   /*
   //пример анализа
   string arr[];
   string.explode(".",var,arr);
   
   if(ArraySize(arr)==2){
       int ticket=StrToInteger(arr[0]);
       
       return (ticket);  
   }
   */
   return (0);
}
//MM
/*цена пункта в валюте депозита*/
double mm.get.price.point(string name){
    double pricePoint=MarketInfo(name,MODE_TICKVALUE);//MarketInfo(name,MODE_TICKVALUE)*(MarketInfo(name,MODE_POINT)/
    return (pricePoint);
}

/*мартингейл*/
double mm.get.lot.martin(string symbol,int id,double lotstart,double K,datetime firstRun){
   
   //поищем в истории последнюю сделку по данной паре данным советником
   double lastlot=0;
   for(int i=OrdersHistoryTotal();i>=0;i--){
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)){
          if(OrderMagicNumber()==id && OrderSymbol()==symbol && OrderCloseTime()>firstRun){
          
            if((StringFind( OrderComment(), "[sl]" ) >= 0 && OrderProfit()<0) || OrderProfit()<0){
                  lastlot=OrderLots();   //последняя сделка была убыточной! вернем лот   
                  break;
            }
            
            break;
          }
      }   
   }   
   
   if(lastlot==0) return (lotstart);//первая либо положительная сделка
   
   double lot=NLot(lastlot*K);      
  
   if(AccountFreeMargin()<MarketInfo(symbol,MODE_MARGINREQUIRED)*lot){ Print("Нехватает маржи для лота ",lot); return (0.0);}
   
   if(lot>MarketInfo(symbol,MODE_MAXLOT)) lot=MarketInfo(symbol,MODE_MAXLOT);
   if(lot<MarketInfo(symbol,MODE_MINLOT)) lot=0.0;
   
   return (lot);
}

double mm(string name,double risk,double sl){
   if(sl==0) return (0);
   double point=mm.get.price.point(name); //стоимость пункта
   double Step =MarketInfo(Symbol(),MODE_LOTSTEP);
   double mn=MarketInfo(Symbol(),MODE_TICKSIZE);
   double lots=NLot(MathFloor((AccountBalance()*risk*0.001)/(sl*point)/Step)*Step);
   return (lots);
}

double mm2(string name,double risk,double slPoint){
   if(slPoint==0) return (0);
   double point=mm.get.price.point(name); //стоимость пункта
   double Step =MarketInfo(Symbol(),MODE_LOTSTEP);
   double mn=MarketInfo(Symbol(),MODE_TICKSIZE);
   double lots=NLot(MathFloor((AccountBalance()*risk*0.001)/(slPoint*point)/Step)*Step);
   return (lots);
}

//блокировка при достижении убытка в %
void mm.balance.set(string name,string var,double start.balance){
   GlobalVariableSet(StringConcatenate(var,".",name,".balance"),start.balance);
}

double mm.balance.get(string name,string var){
   return (NormalizeDouble(GlobalVariableGet(StringConcatenate(var,".",name,".balance")),2));
}

void mm.balance.delete(string name,string var){
   GlobalVariableDel(StringConcatenate(var,".",name,".balance"));
}

double mm.balance.check(string name,string var,double curr.balance){
   double b=GlobalVariableGet(StringConcatenate(var,".",name,".balance"));
   if(b==0) return (0);
   return (NormalizeDouble((curr.balance-b)*100/b,2));
}

double mm.balance.profit(string name,int magic,int &del[]){
   double summ=0;
   int count=0;
   ArrayResize(del,count);//массив ордеров, на момент проверки прибыли
   
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
      if(OrderMagicNumber()!=magic || OrderSymbol()!=name) continue;
      
      if(OrderType()<2){
         summ+=OrderProfit()+OrderCommission()+OrderSwap(); //подсчет профита
         
         ArrayResize(del,count+1);//массив ордеров, на момент проверки прибыли
         del[count]=OrderTicket(); //сохраним тикеты
         count++;
      }
   }
   
   return (summ);
}

//time
int string.hour(string start){
   string param[];
   string.explode(":",start,param);
   if(ArraySize(param)<1) return (0);
   return (StrToInteger(param[0]));
}

int string.minute(string start){
   string param[];
   string.explode(":",start,param);
   if(ArraySize(param)<1) return (0);
   return (StrToInteger(param[1]));
}

int string.seconds(string start){
   string param[];
   string.explode(":",start,param);
   if(ArraySize(param)<1) return (0);
   
   return (StrToInteger(param[2]));
}

/*vitrual tp\sl*/
void virtual.expert(string expert.name){
   Print("Устаревшая функция virtual.expert - не используется, обратитесь к программисту за обновлением библиотек");
}


void virtual.init(){
//id_tp, id_sl
   string del[];
   int count=0,i;
   
   for(i=GlobalVariablesTotal();i>=0;i--){
      if(GlobalVariableName(i)=="") continue;
      
      string param[];
      string.explode(".",GlobalVariableName(i),param);
      
      if((ArraySize(param)==2 && StrToInteger(param[0])>0) || (ArraySize(param)==3 && param[0]=="virtual" && StrToInteger(param[1])>0)){
           int ticket=StrToInteger(param[0]);//тикет
           if(ArraySize(param)==3) ticket=StrToInteger(param[1]);//тикет
           
           if(!virtual.valid(ticket)){
               
               int err=GetLastError();
               //Print(GlobalVariableName(i),"=",err);
               if(ERR_INVALID_TICKET==err || err==4058){
                  //delete global
                  ArrayResize(del,count+1);
                  del[count]=GlobalVariableName(i);
                  
                  count++;
               }   
            
           }else{
           //check tp,sl
               if(!OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) continue;
               
               if(OrderType()>1 || OrderCloseTime()>0) continue; //next order
               
               double pt=0;
               double tp=0;
               double sl=0;
               string n=OrderSymbol();
         
               tp=virtual.get.tp(ticket);
               sl=virtual.get.sl(ticket);
              
               if(tp!=0 && ((dBid(n)>=tp && OrderType()==OP_BUY) || (dAsk(n)<=tp && OrderType()==OP_SELL))){ 
                  order.OrderClose(ticket,-1); 
                  del[count]=GlobalVariableName(i);
                  count++;
               }//close by tp
              
              
               if(sl!=0 && ((dBid(n)<=sl && OrderType()==OP_BUY) || (dAsk(n)>=sl && OrderType()==OP_SELL))){ 
                  order.OrderClose(ticket,-1); 
                  del[count]=GlobalVariableName(i);
                  count++;
               }//close by stop
               
           }
            
      }
         
   
   }
   
   //delete global
   for(i=0;i<count;i++){
      if(del[i]!="" && GlobalVariableCheck(del[i])) 
         GlobalVariableDel(del[i]);
   }
   
}

void virtual.deinit(){
    if(IsTesting()) global.Delete("virtual");
}

//проверим существование тикета, если тикет не существует или тикет закрыт, то вернем false
bool virtual.valid(int ticket){
   if(!OrderSelect(ticket,SELECT_BY_TICKET)) return (false);
   if(OrderCloseTime()==0) return (true);
   return (false);
}

void virtual.OrdersToVirtual(){
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
      
      if(OrderStopLoss()!=0.0 || OrderTakeProfit()!=0.0){
         virtual.set(OrderTicket(),OrderStopLoss(),OrderTakeProfit());
         order.OrderModify(OrderTicket(),OrderOpenPrice(),0,0,OrderExpiration(),CLR_NONE);
      }
      
   }
}

void virtual.VirtualToOrders(){
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
      
      if(OrderStopLoss()==0.0 && OrderTakeProfit()==0.0 && virtual.check(OrderTicket())){
      
         order.OrderModify(OrderTicket(),-1,virtual.get.sl(OrderTicket()),virtual.get.tp(OrderTicket()),0,CLR_NONE);
         
      }
      
   }
}

void virtual.set(int ticket,double sl,double tp){
   if(ticket<=0) return;
   
   string n;
   
   if(tp>=0){
       //if(IsTesting())Print("virtual.set(",ticket,",",sl,",",tp,")");
       
       if(IsTesting()) n=StringConcatenate("virtual.",DoubleToStr(ticket,0),".tp");
       else n=StringConcatenate(DoubleToStr(ticket,0),".tp");
       GlobalVariableSet(n,tp);
   }    
   
   if(sl>=0){
       
       //if(IsTesting())Print("virtual.set(",ticket,",",sl,",",tp,")");
       
       if(IsTesting()) n=StringConcatenate("virtual.",DoubleToStr(ticket,0),".sl");
       else n=StringConcatenate(DoubleToStr(ticket,0),".sl");
       GlobalVariableSet(n,sl);
   }    
}

bool virtual.check(int ticket){
   if(ticket<=0) return;
   string n;
   
   if(IsTesting()) n=StringConcatenate("virtual.",DoubleToStr(ticket,0),".tp");
   else n=StringConcatenate(DoubleToStr(ticket,0),".tp");
   
   if(GlobalVariableCheck(n)) return (true);
   
   if(IsTesting()) n=StringConcatenate("virtual.",DoubleToStr(ticket,0),".sl");
   else n=StringConcatenate(DoubleToStr(ticket,0),".sl");
   
   if(GlobalVariableCheck(n)) return (true);
   
   return (false);
}

double virtual.get.tp(int ticket){
   if(ticket<=0) return;
   string n;
   
   if(IsTesting()) n=StringConcatenate("virtual.",DoubleToStr(ticket,0),".tp");
   else n=StringConcatenate(DoubleToStr(ticket,0),".tp");
   
   if(GlobalVariableCheck(n)) return (GlobalVariableGet(n));
   return (0);
}

double virtual.get.sl(int ticket){
   if(ticket<=0) return;
   string n;   

   if(IsTesting()) n=StringConcatenate("virtual.",DoubleToStr(ticket,0),".sl");
   else n=StringConcatenate(DoubleToStr(ticket,0),".sl");

   if(GlobalVariableCheck(n)) return (GlobalVariableGet(n));
   return (0);
}

void virtual.trailing.esmart(string name,int magic,double level1,double step1,double level2,double step2,double level3,double step3,int trailing.pause.time=5){

   double p=d(name)*dPoint(name);
   datetime tm.buy=0,tm.sell=0;
   
   for(int i=OrdersTotal()-1;i>=0;i--){
         if(!OrderSelect(i,SELECT_BY_POS)) continue;
      
         if(OrderType()>=2) continue;
         if(OrderSymbol()==name && (OrderMagicNumber()==magic || magic==-1)){
      
         string n=OrderSymbol();
      
         double pt=0;
         double stop=virtual.get.sl(OrderTicket());
                  
         if(OrderType()==OP_BUY){
             pt=(dBid(n)-OrderOpenPrice())/p;
            // Print("buy pt=",pt);    
             
             if(pt>=level3 && level3!=0){
                 if((stop==0 || stop < dBid(n)-step3*p) && TimeCurrent()-tm.buy>=trailing.pause.time){
                     virtual.set(OrderTicket(),dBid(n)-step3*p,0);
                     tm.buy=TimeCurrent();
                     continue;
                 }    
             }
             
             if(pt>=level2 && level2!=0){
                 if((stop==0 || stop < dBid(n)-step2*p) && TimeCurrent()-tm.buy>=trailing.pause.time){
                     virtual.set(OrderTicket(),dBid(n)-step2*p,0);
                     tm.buy=TimeCurrent();
                     continue;
                 }    
             }
             
             if(pt>=level1 && level1!=0){
                 if((stop==0 || stop < dBid(n)-step1*p) && TimeCurrent()-tm.buy>=trailing.pause.time){
                     virtual.set(OrderTicket(),dBid(n)-step1*p,0);
                     tm.buy=TimeCurrent();
                     continue;
                 }
             }
             
         }    
            
         if(OrderType()==OP_SELL){
             pt=(OrderOpenPrice()-dAsk(n))/p;
            // Print("sell pt=",pt);    
             if(pt>=level3 && level3!=0){
                if((stop==0 || stop>dAsk(n)+step3*p) && TimeCurrent()-tm.sell>=trailing.pause.time){
                     order.OrderModify(OrderTicket(),-1,dAsk(n)+step3*p,-1,0,Green);
                     virtual.set(OrderTicket(),dAsk(n)+step3*p,0);
                     tm.sell=TimeCurrent();
                     continue;
                } 
             }      
             
             if(pt>=level2 && level2!=0){
                if((stop==0 || stop>dAsk(n)+step2*p) && TimeCurrent()-tm.sell>=trailing.pause.time){
                     virtual.set(OrderTicket(),dAsk(n)+step2*p,0);
                     tm.sell=TimeCurrent();
                     continue;
                } 
             } 
             
             if(pt>=level1 && level1!=0){
                if((stop==0 || stop>dAsk(n)+step1*p) && TimeCurrent()-tm.sell>=trailing.pause.time){
                     virtual.set(OrderTicket(),dAsk(n)+step1*p,0);
                     tm.sell=TimeCurrent();
                     continue;
                } 
             }
         }    
      }
   }
}   

//symbols raw,sel;
int GetAllSymbols(string &Symbols[], bool Selected,double maxspread)
{  
   string SymbolsFileName;  
   int SymbolsNumber,Offset; 
   
   if(Selected) SymbolsFileName = "symbols.sel";
   else         SymbolsFileName = "symbols.raw";
   
   int hFile = FileOpenHistory(SymbolsFileName, FILE_BIN|FILE_READ);
   
   if(hFile < 0) return(-1);
   
   if(Selected) { SymbolsNumber = (FileSize(hFile) - 4) / 128; Offset = 116;  }
   else         { SymbolsNumber = FileSize(hFile) / 1936;      Offset = 1924; }
   
   //ArrayResize(Symbols, SymbolsNumber);
   
   if(Selected) FileSeek(hFile, 4, SEEK_SET);
   int j=0;   
   for(int i = 0; i < SymbolsNumber; i++){ 
         
      string smb = FileReadString(hFile, 12);
      
      if(smb!=""){
         if(MarketInfo(smb,MODE_ASK)-MarketInfo(smb,MODE_BID)<maxspread*p(smb) || maxspread==0){
            ArrayResize(Symbols, j+1);
            Symbols[j]=smb;
            j++;
         }
      }
      
      FileSeek(hFile, Offset, SEEK_CUR);   
   }
   
   FileClose(hFile);
   
   return(SymbolsNumber);
}  

void reconnect ()
{
    int h = WindowHandle (Symbol(), Period());
    if (h != 0)
    {
        //---- Управляем реконнектом посредством кнопки "Советники"
        if (IsExpertEnabled())
        {
            while (!IsConnected() && IsExpertEnabled())
            {
                  int hmt = GetAncestor (h, 2); // фокус на окно терминала
                  
                  if (hmt != 0) {
                     PostMessageA (hmt, WM_COMMAND, 37400, 0);
                  }
                  
                  Sleep (2000);
            }
        }
     }   
}   
//part Close
/*
lot - суммарный лот
*/
int get.part(int ticket,double &lot[]){
   
   int part=0;
   lot[0]=0;
   datetime tOpen=0;
   int magic;
   double open;
   string name;
   if(!OrderSelect(ticket,SELECT_BY_TICKET)) return (-1);
   
   open=OrderOpenPrice();
   tOpen=OrderOpenTime();
   magic=OrderMagicNumber();
   name=OrderSymbol();
   lot[0]=OrderLots(); 
   //Print("get.part: ",lot);
   
   for(int i=OrdersHistoryTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)) continue;
      
      if(OrderMagicNumber()==magic && OrderSymbol()==name && NormalizeDouble(OrderOpenPrice(),Digits)==NormalizeDouble(open,Digits) && OrderOpenTime()==tOpen){
         lot[0]+=OrderLots();
         part++;
      }
   }
   
   if(!OrderSelect(ticket,SELECT_BY_TICKET)) return (-1);  
   
   //Print("get.part: ",part," ",lot," == ", OrderLots());
   return (part); //вернем сколько раз уже закрывались
}

/*
int get.part(string name,int magic,double open,double &lot){
   
   int part=0;
   for(int i=OrdersHistoryTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)) continue;
      
      if(OrderMagicNumber()==magic && OrderSymbol()==name && NormalizeDouble(OrderOpenPrice(),Digits)==NormalizeDouble(open,Digits)){
         lot+=OrderLots();
         part++;
      }
   }
     
   return (part); //вернем сколько раз уже закрывались
}*/

double mm.get.lot(string name,double lot.def,double risk,double startdepo)
  {
   double lot=lot.def;
   if(risk==0) return (lot);
   
   lot=NLot(AccountBalance()*risk/startdepo);
   if(lot>MarketInfo(name,MODE_MAXLOT)) lot=NLot(MarketInfo(name,MODE_MAXLOT));
   if(lot<MarketInfo(name,MODE_MINLOT)) lot=NLot(MarketInfo(name,MODE_MINLOT));
   return(lot);
}

//вспомогательные функции
//разложение кросса на пары
void get.subsymbol(string cross,string &sub[2]){
   string x1=StringSubstr(cross,0,3);   
   string x2=StringSubstr(cross,3,3);
   
   sub[0]=get.subname(x1);
   sub[1]=get.subname(x2);   
   
}

string get.subname(string x1){
   string sub1="";
   if(MarketInfo(StringConcatenate(x1,"USD"),MODE_BID)>0) sub1=StringConcatenate(x1,"USD");
   else if(MarketInfo(StringConcatenate("USD",x1),MODE_BID)>0) sub1=StringConcatenate("USD",x1);
   //else Print("Ошибка получения имени символа! -> ",x1);
   
   return (sub1);
}

//отладочные 
//выводим все глобалльные переменные, которые содержат строку
void global.print(string str=""){
   int j=0;
   for(int i=0;i<GlobalVariablesTotal();i++){
      string s=GlobalVariableName(i);
      if(s=="") continue;
      if(StringFind(s,str)>=0 || str==""){
         Print("(",j,") ",s," = ",GlobalVariableGet(s));
         j++;
      }
   }
}


void ExpertEnabled(bool Switch) {

  int HandlWindow = WindowHandle(Symbol(), Period()); 
  int HandlMT4;     
  int HandlToolbar; 
  int    ArIntTemp[1];

  if(Switch == true){
    if(!IsExpertEnabled()){
      HandlMT4 = GetAncestor(HandlWindow, 2);   
      HandlToolbar = GetDlgItem(HandlMT4, 0x63);
      ArIntTemp[0]=HandlToolbar;
      SendMessageA(HandlMT4, WM_COMMAND, 33020, HandlToolbar);
     }
     
   }else{
    
    if(IsExpertEnabled()){
      HandlMT4 = GetAncestor(HandlWindow, 2);   
      HandlToolbar = GetDlgItem(HandlMT4, 0x63);
      ArIntTemp[0]=HandlToolbar;
      SendMessageA(HandlMT4, WM_COMMAND, 33020, HandlToolbar);
     }
   }
   
 }
 
 /*функции для адаптации торговли на ренко графиках*/

//проверим, график нестандартный? 
 bool bar.isRenko(int TF){
   if (TF==1||TF==5||TF==15||TF==30||TF==60||TF==240||TF==1440||TF==10080||TF==43200) return (false);
   return (true);
 }
 
 void renko.Comment(){
   if (!IsTesting()) {
      if (IsExpertEnabled())Comment("");
      else Comment("Советник отключен. Теперь можно изменить настройки. Для запуска обязательно зайдите в Свойства советника и нажмите кнопку ОК");
   }
 }  
 
 void renko.time(){
   Comment("Советник в работе, текущее время: ",TimeToStr(TimeCurrent(),TIME_MINUTES|TIME_SECONDS));
 }
 
 //коробки
 void get.box(string name,string start,string end,double &high[1],double &low[1]){
   int h.start=string.hour(start);
   int h.end=string.hour(end);
   int m.start=string.minute(start);
   int m.end=string.minute(end);
   
   datetime tm.start,tm.end;
   high[0]=0; low[0]=0;
   if(h.end<h.start && Hour()>=0 && Hour()<h.start){
   //если у нас время начала больше (фактически с прошлого дня), то надо это учесть
       tm.start=iTime(name,PERIOD_D1,1)+h.start*3600+m.start*60;
       tm.end=iTime(name,PERIOD_D1,0)+h.end*3600+m.end*60;
   }  

   if(h.end<h.start && Hour()>=h.start && Hour()>0){
   //если у нас время начала больше (фактически с прошлого дня), то надо это учесть
       tm.start=iTime(name,PERIOD_D1,0)+h.start*3600+m.start*60;
       tm.end=iTime(name,PERIOD_D1,0)+h.end*3600+m.end*60+24*3600;
   }  
   
   if(h.end>=h.start){
   //если у нас время начала больше (фактически с прошлого дня), то надо это учесть
       tm.start=iTime(name,PERIOD_D1,0)+h.start*3600+m.start*60;
       tm.end=iTime(name,PERIOD_D1,0)+h.end*3600+m.end*60;
   }  
   
  // Print(TimeToStr(tm.start)," ",TimeToStr(tm.end));
   int pos.start=iBarShift(name,0,tm.start,false);
   int pos.end=iBarShift(name,0,tm.end,false);
   int len=MathAbs(pos.start-pos.end)+1;
   
   //Print(iHighest(name,0,MODE_HIGH,len,pos.end)," -- ",iLowest(name,0,MODE_LOW,len,pos.end));
   high[0]=iHigh(name,0,iHighest(name,0,MODE_HIGH,len,pos.end));
   low[0]=iLow(name,0,iLowest(name,0,MODE_LOW,len,pos.end));
}

void get.boxgmt(string name,string start,string end,double &high[1],double &low[1],int timeoffset=0){
   int h.start=string.hour(start);
   int h.end=string.hour(end);
   int m.start=string.minute(start);
   int m.end=string.minute(end);
   
   datetime tm.start,tm.end;
   high[0]=0; low[0]=0;
   if(h.end<h.start && Hour()>=0 && Hour()<h.start){
   //если у нас время начала больше (фактически с прошлого дня), то надо это учесть
       tm.start=iTime(name,PERIOD_D1,1)+h.start*3600+m.start*60+timeoffset*3600;
       tm.end=iTime(name,PERIOD_D1,0)+h.end*3600+m.end*60+timeoffset*3600;
   }  

   if(h.end<h.start && Hour()>=h.start && Hour()>0){
   //если у нас время начала больше (фактически с прошлого дня), то надо это учесть
       tm.start=iTime(name,PERIOD_D1,0)+h.start*3600+m.start*60+timeoffset*3600;
       tm.end=iTime(name,PERIOD_D1,0)+h.end*3600+m.end*60+24*3600+timeoffset*3600;
   }  
   
   if(h.end>=h.start){
   //если у нас время начала больше (фактически с прошлого дня), то надо это учесть
       tm.start=iTime(name,PERIOD_D1,0)+h.start*3600+m.start*60+timeoffset*3600;
       tm.end=iTime(name,PERIOD_D1,0)+h.end*3600+m.end*60+timeoffset*3600;
   }  
   
  // Print(TimeToStr(tm.start)," ",TimeToStr(tm.end));
   int pos.start=iBarShift(name,0,tm.start,false);
   int pos.end=iBarShift(name,0,tm.end,false);
   int len=MathAbs(pos.start-pos.end)+1;
   
   //Print(iHighest(name,0,MODE_HIGH,len,pos.end)," -- ",iLowest(name,0,MODE_LOW,len,pos.end));
   high[0]=iHigh(name,0,iHighest(name,0,MODE_HIGH,len,pos.end));
   low[0]=iLow(name,0,iLowest(name,0,MODE_LOW,len,pos.end));
   
}

/*пример обработчика ренко*/
void renko.start(int tf,int delay){
   static bool lastButton=0;
   
   if(bar.isRenko(tf) && IsExpertEnabled()){
      while (true){  
           if(lastButton!=IsExpertEnabled()){ lastButton=IsExpertEnabled();  renko.Comment();}
           if(!IsExpertEnabled()) break;

           //start(); //выполнение основной программы
           Sleep(delay); //задержка без нее подет подвисать терминал
      }
   }         
}   

string fx(string name,string Symbols[]){
   int len1,len2,len;
   if(name=="") return ("");
   
   for(int i=0;i<ArraySize(Symbols);i++){
      len1=StringLen(Symbols[i]);
      len2=StringLen(name);
      len=MathMin(len1,len2);
      
      if(MarketInfo(Symbols[i],MODE_PROFITCALCMODE)==0) len=6;
      //if(StringSubstr(Symbols[i],0,len)=="GBPUSD") Print(StringSubstr(name,0,len));
      if(StringSubstr(Symbols[i],0,len)==StringSubstr(name,0,len)) return (Symbols[i]);
   }
   
   Print("Критическая ошибка: ",name," не найден в окне Обзор рынка или наименование символа отличается!");
   return (name);
}


//set files
/*функции для загрузки данных из сет файлов*/
//загрузка сет файла и получения параметров
int load.set(string name,string &lines[]){
//StringConcatenate(WindowExpertName(),"/",name,".set")
   int h=FileOpen(name,FILE_READ|FILE_CSV);
   ArrayResize(lines,0);
   int l=0;
   if(h!=-1){
      //загрузка файла set
      while(!FileIsEnding(h)){
         string s=FileReadString(h);
         if(s=="" || StringFind(s,",")>0) continue;
         ArrayResize(lines,l+1);
         lines[l]=s; //сохраним все переменные из файла в массив для последующего поиска и выборки
         l++;
      }   
   
      FileClose(h);
   }
   
   return (l);
}

string get.setFileString(string lines[],string match){
   for(int i=0;i<ArraySize(lines);i++){
      if(StringFind(lines[i],match)==0){
         int pos=StringFind(lines[i],"=");
         if(pos>0){
            return (StringSubstr(lines[i],pos+1));
         }
      }
   }

   Print("Invalid param: ",match);
   return ("");
}

string paramString(string lines[],string match){ return (get.setFileString(lines,match));}
int paramInt(string lines[],string match){ return (StrToInteger(get.setFileString(lines,match)));}
double paramDouble(string lines[],string match){return (StrToDouble(get.setFileString(lines,match)));}
bool paramBool(string lines[],string match){ return (StrToInteger(get.setFileString(lines,match)));}
datetime paramTime(string lines[],string match){ return (StrToInteger(get.setFileString(lines,match)));}

//draw
//draw library
void draw.delete(string obj_name){
   string del[];
   ArrayResize(del,ObjectsTotal());
   for(int i=ObjectsTotal();i>=0;i--) del[i]=ObjectName(i);
   for(i=0;i<ArraySize(del);i++)  if(del[i]!="" && StringFind(del[i],obj_name,0)>=0) ObjectDelete(del[i]);
}  

void draw.obj.label(string name,int window){
   if(ObjectFind(name)<0) ObjectCreate(name,OBJ_LABEL,window,1,1);
}

void draw.obj.rectangle(string name,int bar1,double price1, int bar2, double price2,color cl,int window){
   if(ObjectFind(name)<0) ObjectCreate(name,OBJ_RECTANGLE,window,0,0,0,0);
   datetime tm1=iTime(Symbol(),Period(),bar1);
   datetime tm2=iTime(Symbol(),Period(),bar2);
   
   ObjectSet(name,OBJPROP_TIME1,tm1);
   ObjectSet(name,OBJPROP_TIME2,tm2);
   ObjectSet(name,OBJPROP_PRICE1,price1);
   ObjectSet(name,OBJPROP_PRICE2,price2);
   ObjectSet(name,OBJPROP_COLOR,cl);
   
}


void draw.setxy(string name,int x,int y){
   if(ObjectFind(name)>=0){
         ObjectSet(name,OBJPROP_XDISTANCE,x);
         ObjectSet(name,OBJPROP_YDISTANCE,y);
   }
}

void draw.color(string name,color c){ ObjectSet(name,OBJPROP_COLOR,c);}

void draw.corner(string name,int corner){
   if(ObjectFind(name)>=0)ObjectSet(name,OBJPROP_CORNER,corner);
}

void draw.settext(string name,string text,int size,string font="Arial Black",color cl=Black){
   if(ObjectFind(name)>=0)ObjectSetText(name,text,size,font,cl);
}
//help://constants_wingdings/
void draw.setarrow(string name,int code,int size,color cl){
   if(ObjectFind(name)>=0)ObjectSetText(name,CharToStr(code),size,"Wingdings",cl);
}

void draw.label(string name,string text,int x,int y,color cl,int size=12){
   draw.obj.label(name,0);
   draw.setxy(name,x,y);
   draw.corner(name,0); //left top
   draw.settext(name,text,size,"Arial",cl);
}

void draw.label.bold(string name,string text,int x,int y,color cl,int size=12){
   draw.obj.label(name,0);
   draw.setxy(name,x,y);
   draw.corner(name,0); //left top
   draw.settext(name,text,size,"Arial Black",cl);
}

void draw.label2.bold(string name,string text,int x,int y,color cl,int size=12){
   draw.obj.label(name,0);
   draw.setxy(name,x,y);
   draw.corner(name,2); //left top
   draw.settext(name,text,size,"Arial Black",cl);
}

void draw.obj.vline(string name,int window){
   if(ObjectFind(name)<0) ObjectCreate(name,OBJ_VLINE,window,0,0);
}

void draw.obj.hline(string name,int window){
   if(ObjectFind(name)<0) ObjectCreate(name,OBJ_HLINE,window,0,0);
}

string string.type(int type){
   switch(type){
   case 0: return ("BUY");
   case 1: return ("SELL");
   case 2: return ("BUYLIMIT");
   case 3: return ("SELLLIMIT");
   case 4: return ("BUYSTOP");
   case 5: return ("SELLSTOP");
   default: return ("UNKNOWN");
   }
}


