Разрывы связи

 
Здравствуйте.
Занялся программированием на MQL около месяца назад, сейчас пишу второй советник (первый при прогоне в тестере терял со скоростью спреда:(
По ходу дела возник вопрос по технической части, а именно:
Когда случаются разрывы в связи, и в разрыв попадает хотя бы 1 бар, то после восстановления связи этот бар тоже должен быть обсчитан.
Сначала я предполагал использовать такой код:
//...
int Future;
datetime LastTime;
//...
int start()
   {
   if(LastTime==Time[0])//тот же бар
      {
      //...блок советника , выполняемый на каждом тике...
      return;
      }
   if(LastTime<Time[0])//новый бар или был разрыв связи
      {
      Future=0;
      for(int n=1;;n++)
         {
         if(Time[n]==LastTime) {Future=n;break;}
         }
      while(Future>0)
         {
         //...блоки советника , выполняемые при появлении нового бара...
         Future--;
         }
      LastTime=Time[0];
      return;
      }
   }
Однако затем я обратил внимание, что при восстановлении связи после разрыва сначала появляется один или несколько тиков последнего бара, а затем подгружается вся пропущенная история. Поэтому первый вариант кода, видимо, некорректен.
Уже при написании поста пришла идея:
//...
int Future;
datetime Time_0_bar;//время 0 бара
datetime LastTime;//время последнего бара
//...
int start()
   {
   if(LastTime==Time[0])//тот же бар + не было разрывов
      {
      //...блок советника , выполняемый на каждом тике...
      return;
      }
   if(LastTime<Time[0])//новый бар или был разрыв связи
      {
      if(Time[0]==Time_0_bar)return;//ждём
      if(Time[0]-Period()>LastTime)//если был разрыв связи (и появился новый бар)
         {Time_0_bar=Time[0]; return;}//ждём нового бара
      Future=0;
      for(int n=1;;n++)
         {
         if(Time[n]==LastTime) {Future=n;break;}
         }
      while(Future>0)
         {
         //...блоки советника , выполняемые при появлении нового бара...
         Future--;
         }
      LastTime=Time[0];
      Time_0_bar=Time[0];
      return;
      }
   }
Однако и здесь есть два недостатка:
- до появления новой свечи история может так и не подгрузиться
- на свечах больших таймфреймов это приведёт к большой задержке во времени
В связи с этим вопрос: существует ли более надёжный алгоритм (шаблон) кода для разрешения такой проблемы (ведь наверняка те, кто давно пишет на MQL, сталкивались с подобным)
Заранее спасибо за ответ
 

я использую код

   if(!IsConnected())return(1);

   if(MarketInfo(Symbol(),MODE_TRADEALLOWED) != 1)return(1);
 

Если происходил рекконект и это было известно - логично взводить флаг!

затем пытаться докачать котировки и только после этого пускать обсчеты

---

при ошибках связи есть неплохие способы рекконекта было в CODEBASE!

--

по докачке котировок так же можно поискать готовые решения в CODEBASE

с контролями ! на пропуски и т п

по идее надо проконтролирвать прокачку котировок

---

сложности будут так же на переходах с пятницы на понедельник

там надо качесвенно отловить точку старта и завершения

ну или не торговать несколько баров ! по рабочему тф в понедельник

 
Много полезной информации по вопросу разрывов и т.п. есть в скрипте history data analysis от Bagadul https://www.mql5.com/ru/code/8039 (если
кому-то будет надо).

2 kharko: действительно, с IsConnected() всё намного проще, только эксперт приходится делать зацикленным:

int Future;
datetime LastTime;            // Время последнего бара
int Work=0;                         // -1 = непреодолимая ошибка, 0 = выходной/подготовка к работе, 1 =  всё работает
double Time_Lost;             // время разрыва связи
int Time_NoGap;                // количество отсутствующих подряд баров, не считаемое разрывом (зависит от ТФ, устанавливается в init())
		           // для 1M=15, для 5M=3, для 15M=1,  для остальных ТФ=0,
extern bool Close_All_Pos_Before_Holidays=true;
   // Если true, перед выходными все открытые советником ордера закрываются, отложенные удаляются
bool All_Close=false;          // Метка, что ордера действительно были закрыты (устанавливается в ф-ции закрытия ордеров)
//-------------------------------------------------------------------------------------------------------
int start()
   {
   while(Work!=-1) /*В ходе работы не было непреодолимых ошибок
	(такие м.б. объявлены из многих мест программы, напр. из ф.-ции установки ордеров)*/
      {
      if(!IsConnected())//если нет связи
         {
         double Time_Befor=TimeCurrent();//время начала разрыва связи
         while(!IsConnected())//пока нет связи
            {
            Sleep(30000);//ждём 30 сек.
            }
         // связь появилась ждём первого тика
         double Time_After=TimeCurrent();
         while(Time_After==Time_Befor)//первый тик ещё не пришёл
            {
            Sleep(10000);//ждём 10 сек.
            Time_After=TimeCurrent();
            }
         // есть новый тик
         Time_Lost=Time_After-Time_Befor;//секунд в разрыве
         if(Time_Lost>=604800)
            {
            Alert("связи не было больше недели:-о)");
            Alert("Необходима переустановка советника");
            Close_All_Orders();//Функция, закрывающая все открытые ордера
            Work=-1;
            return;
            }
         Time_Lost=MathFloor(Time_Lost/(60*Period()));//баров в разрыве
            /*баров обычно пропущено Time_Lost или Time_Lost-1,
            иначе история недогружена или отсутствуют отдел. бары  или разрыв связи был с пятницы на воскресенье*/
         RefreshRates();
         Sleep(30000);//Подождём пока данные обновятся
         int n=0;
         while(n<=Time_Lost)
            {
            if(Time[n]==LastTime)break;//нашли последний бар перед разрывом
            int Time_Gap=(Time[n]-Time[n+1])/(60*Period());
            if(Time[n+1]+60*Period()!=Time[n])//подозрение на разрыв в ряду баров
               {
               if((Time[n]-1233532800)%604800<(Time[n+1]-1233532800)%604800)
                  {//если это разрыв на выходные
                  if(Period()==240)Time_Gap-=12;
                  else Time_Gap-=3000/Period()-1;
                  }//уменьшили разрыв на размер выходных
               }
            if(Time_Gap-1>Time_NoGap)
               Alert("Внимание: не хватает ",Time_Gap," баров в промежутке от ",
               TimeToStr(Time[n+1])," до ",TimeToStr(Time[n]));
            n++;
            }
         Future=n;
         }//выход из обработки ошибок связи
      if(MarketInfo(Symbol(),MODE_TRADEALLOWED)!=1)
         //если торговля не разрешена(сессия закрыта)
         return;//выходим
      if(LastTime==Time[0])//тот же бар
         {
         //блок, выполняемый на каждом тике
         }
      if(LastTime<Time[0])//новый бар
         {
         Total+=Future;
         while(Future>0)
            {//Блоки, выполняемые при появлении нового бара
            Future--;}
         LastTime=Time[0];
         }
      if(Work==0)//первый тик после выходных
         {Sleep(600*1000);//ждём 10 минут после начала сессии
         Work=1;
         continue;}
      if(All_Close==true)Open_All_Orders();
         //открываем позиции после выходных, если закрывали
      if(TimeDayOfWeek(TimeCurrent())==5)
         {
         if(TimeHour(TimeCurrent())==21)
            {
            if(TimeMinute(TimeCurrent())>30)
               {//за полчаса до закрытия на выходные
               if(Close_All_Pos_Before_Holidays==true)
                  {
                  Close_All_Orders();//Функция закрытия ордеров
                  Work=0;
                  Sleep(1860*1000);//ждём завершения сессии
                  return;//выходим
                  }
               }
            }
         }
      Sleep(10000);//ждём 10 сек.
      }
   }  

Пару замечаний к коду: счёт открыт в Teletrade, и там недельная сессия обычно закрывается на первых тиках 22:00 пятницы, а открывается в
00:00 понедельника или позже(швейцарское время). Соответственно, все числа подобраны под эти данные. 1233532800-открытие 2 февраля
2009, понедельник, 00:00 (можно взять любой другой понедельник), но у брокеров в других часовых поясах это число изменится.
Также бывают дни (например, перед новым годом), когда сокращенная неделя или нестандартное закрытие в пятницу - тут эта программа не
поможет, надо всё делать самому (если есть желание закрыть позиции перед выходными, закрывать вручную). Либо писать нестандартные
даты закрытия в отдельный файл, и чтобы советник периодически считывал данные из этого файла
Обращаю внимание, что код ещё не проверен в торговле.

Также хотелось бы услышить компетентное мнение по следующим вопросам:
1) Вызов RefreshRates() является достаточным для подкачки всех пропущенных данных?
2) обновление истории происходит внутри функции RefreshRates() или после её вызова? (я в программе сделал паузу в 30 секунд после вызова
RefreshRates(), чтобы если пропущено много данных, всё обновилось; так нужна ли вообще эта пауза?)

3) К вопросу о значениии Sleep() при проверке !IsConnected() :

Бывают ли разрывы в связи размером в несколько секунд, которые не видны при обычной торговле, но учитываются терминалом, и если да, то как часто

Причина обращения: