MT5 и скорость в боевом исполнении - страница 62

 
Rorschach:
реалтайм ядро может как то помочь?

Ставьте заведомо больше ядер и не доводите ситуацию до 100% загрузок одиночных ядер.

В сказки не надо верить, процессоры и планировщик потоков не работают так, как вы представляете себе.

 
Anton:

В последних сборках прием потока тиков не влияет даже теоретически. Практически SymbolInfoTick уже сейчас работает с кэшом, но отдельные граждане продолжают искать черную кошку.

А у него в тесте и не 80% даже. Там 6 агентов пашут на 4 ядрах, т.е. гарантировано 100%.

Вопрос только в том, как справляется с этой ситуаций планировщик задач его системы. При этом делаются утверждения, что виновата именно реализация терминала.

Т.е. искусственно создается ситуация, когда компьютер загружен сверх всякой меры, когда на нем тормозит буквально всё, а потом делаются заявления в стиле "ой, смотрите, а почему это вот там терминал иногда имеет лаги".

Закроем глаза, что даже в таких условиях это "примерно 0.01%" - к черту подробности! Достаточно заявить, что "средняя температура по больнице никого не волнует", "лаги создают проблемы во время торговли" и "хотим HFT".

Более того, конечно же, хотим чтобы HFT был в 20 экспертов на старом офисном десктопе или дохлой виртуалке.

PS PositionSelectByTicket() в своей реализации безусловно имеет доступ к разделяемому ресурсу с синхронизацией доступа. А если не селектить позицию на каждом вызове, то вы читаете старую цену. Проще было сделать "снепшот" через SymbolInfoDouble.

спасибо

вопрос мой возник, т.к. полгода назад оптимизировал код и тестировал скорость работы системных функций, полгода назад SymbolInfoDouble был медленнее SymbolInfoTick 

а так в целом, наверное правду говорите, сегодня специально гуглил пару статей про кэш многоядерных процессоров (давно не интересовался этой инфой ),

вот краткая статья https://i2hard.ru/publications/25666/

суть, что на выполнение в АЛУ попадают данные исключительно из L1-кэша, который очень мал, и если загружать процессор на "всю катушку", то действительно - тест превратится в тест операционки + тест скорости работы процессорного кэша (загрузки, предсказания L1+L3 данных) , но никак не в тестирование производительности кода (приложения)

 

fxsaber , а если поставить низкий приоритет для агентов в диспетчере задач, а для MT5 высокий?

Не могу найти утилитку, которая бы блокировало выделение для всех программ/потоков ОС ресурса в виде конкретного потока ЦП, иначе можно было бы для MT5 резервировать поток и автоматически блокировать его занятие для других программ, что могло бы в теории снизить лаги.

 
Anton:

В последних сборках прием потока тиков не влияет даже теоретически. Практически SymbolInfoTick уже сейчас работает с кэшом, но отдельные граждане продолжают искать черную кошку.

Отдельный гражданин достал из широких штанин дубликатом бесценного груза MQL-код, который показал, что в одних и тех же условиях костыль работает быстрее штатной функции.

Но Вы утверждаете, что Ваша функция хорошая, просто она имеет ограничения на условия использования.

А у него в тесте и не 80% даже. Там 6 агентов пашут на 4 ядрах, т.е. гарантировано 100%.

Вопрос только в том, как справляется с этой ситуаций планировщик задач его системы. При этом делаются утверждения, что виновата именно реализация терминала.

Т.е. искусственно создается ситуация, когда компьютер загружен сверх всякой меры, когда на нем тормозит буквально всё, а потом делаются заявления в стиле "ой, смотрите, а почему это вот там терминал иногда имеет лаги".

6/8 - ничего не тормозит. Браузеры, компиляция, отладка и т.д. параллельно пашут без каких-либо намеков на тормоза.

Но сейчас специально все отключил, оставив только 4/8 Агента. Ситуация не изменилась с тормозами Вашей функции.

Более того, конечно же, хотим чтобы HFT был в 20 экспертов на старом офисном десктопе или дохлой виртуалке.

Быстрая машина использовалась. И только 6 чартов уже давали тормоза.

PS PositionSelectByTicket() в своей реализации безусловно имеет доступ к разделяемому ресурсу с синхронизацией доступа. А если не селектить позицию на каждом вызове, то вы читаете старую цену. Проще было сделать "снепшот" через SymbolInfoDouble.

И такое использую.

// Снепшот SymbolInfoTick для текущего символа.
bool SymbolInfoTick( MqlTick &Tick )
{
  static MqlTick PrevTick = {0};
  static ulong PrevTime = 0;
  
  const ulong NewTime = GetMicrosecondCount();
  const bool Res = (NewTime - PrevTime < 1000) || (::SymbolInfoTick(_Symbol, PrevTick) && (bool)(PrevTime = NewTime));
  
  Tick = PrevTick;
  
  return(Res);
}
 

О какой скорости в боевом исполнении может идти речь когда в терминале есть проблемы. 

Эксперт сканрует все финансовые инструменты и ищет заданный паттерн.

Натыкается на финансовый инструмент и виснет наглухо!!!

Код из справки, я проставил только шаги, фин инструмент с проблемой и таймер:

//+------------------------------------------------------------------+ 
//|                                              TestLoadHistory.mq5 | 
//|                        Copyright 2009, MetaQuotes Software Corp. | 
//|                                              https://www.mql5.com | 
//+------------------------------------------------------------------+ 
#property copyright "2009, MetaQuotes Software Corp." 
#property link      "https://www.mql5.com" 
#property version   "1.02" 
#property script_show_inputs 
//--- input parameters 
input string          InpLoadedSymbol="RTSCHH1";   // Symbol to be load 
input ENUM_TIMEFRAMES InpLoadedPeriod=PERIOD_H1;  // Period to be load 
input datetime        InpStartDate=D'2006.01.01'; // Start date 
//+------------------------------------------------------------------+ 
//| Script program start function                                    | 
//+------------------------------------------------------------------+ 
void OnStart() 
  { 
   Print("Start load",InpLoadedSymbol+","+GetPeriodName(InpLoadedPeriod),"from",InpStartDate); 
//--- 
   int res=CheckLoadHistory(InpLoadedSymbol,InpLoadedPeriod,InpStartDate); 
   switch(res) 
     { 
      case -1 : Print("Unknown symbol ",InpLoadedSymbol);             break; 
      case -2 : Print("Requested bars more than max bars in chart "); break; 
      case -3 : Print("Program was stopped ");                        break; 
      case -4 : Print("Indicator shouldn't load its own data ");      break; 
      case -5 : Print("Load failed ");                                break; 
      case  0 : Print("Loaded OK ");                                  break; 
      case  1 : Print("Loaded previously ");                          break; 
      case  2 : Print("Loaded previously and built ");                break; 
      default : Print("Unknown result "); 
     } 
//--- 
   datetime first_date; 
   SeriesInfoInteger(InpLoadedSymbol,InpLoadedPeriod,SERIES_FIRSTDATE,first_date); 
   int bars=Bars(InpLoadedSymbol,InpLoadedPeriod); 
   Print("First date ",first_date," - ",bars," bars"); 
//--- 
  } 
//+------------------------------------------------------------------+ 
//|                                                                  | 
//+------------------------------------------------------------------+ 
int CheckLoadHistory(string symbol,ENUM_TIMEFRAMES period,datetime start_date) 
  { 
  Print(" === 1 === ");
   datetime first_date=0; 
   datetime times[100]; 
//--- check symbol & period 
   if(symbol==NULL || symbol=="") symbol=Symbol(); 
   if(period==PERIOD_CURRENT)     period=Period(); 
//--- check if symbol is selected in the MarketWatch 
   if(!SymbolInfoInteger(symbol,SYMBOL_SELECT)) 
     { 
      if(GetLastError()==ERR_MARKET_UNKNOWN_SYMBOL) return(-1); 
      SymbolSelect(symbol,true); 
     } 
     
     ulong time = GetMicrosecondCount();
     Print(" === 2 === ",first_date);
//--- check if data is present 
  bool date = SeriesInfoInteger(symbol,period,SERIES_FIRSTDATE,first_date); 
   
   Print(" === 2.1 === ",(time - GetMicrosecondCount()));
   
   if(first_date>0 && first_date<=start_date) return(1); 
//--- don't ask for load of its own data if it is an indicator 

Print(" === 2.2 === ");
   if(MQL5InfoInteger(MQL5_PROGRAM_TYPE)==PROGRAM_INDICATOR && Period()==period && Symbol()==symbol) 
      return(-4); 
//--- second attempt 
Print(" === 2.3 === ");
   if(SeriesInfoInteger(symbol,PERIOD_M1,SERIES_TERMINAL_FIRSTDATE,first_date)) 
     { 
      //--- there is loaded data to build timeseries 
      Print(" === 2.4 === ");
      if(first_date>0) 
        { 
         //--- force timeseries build 
         CopyTime(symbol,period,first_date+PeriodSeconds(period),1,times); 
         //--- check date 
         Print(" === 2.5 === ");
         if(SeriesInfoInteger(symbol,period,SERIES_FIRSTDATE,first_date)) 
            if(first_date>0 && first_date<=start_date) return(2); 
        } 
     } 
     
     Print(" === 3 === ");
     
//--- max bars in chart from terminal options 
   int max_bars=TerminalInfoInteger(TERMINAL_MAXBARS); 
//--- load symbol history info 
   datetime first_server_date=0; 
   while(!SeriesInfoInteger(symbol,PERIOD_M1,SERIES_SERVER_FIRSTDATE,first_server_date) && !IsStopped()) 
      Sleep(5); 
//--- fix start date for loading 

Print(" === 4 === ");


   if(first_server_date>start_date) start_date=first_server_date; 
   if(first_date>0 && first_date<first_server_date) 
      Print("Warning: first server date ",first_server_date," for ",symbol, 
            " does not match to first series date ",first_date); 
//--- load data step by step 

Print(" === 5 === ");

   int fail_cnt=0; 
   while(!IsStopped()) 
     { 
      //--- wait for timeseries build 
      while(!SeriesInfoInteger(symbol,period,SERIES_SYNCHRONIZED) && !IsStopped()) 
         Sleep(5); 
      //--- ask for built bars 
      int bars=Bars(symbol,period); 
      if(bars>0) 
        { 
         if(bars>=max_bars) return(-2); 
         //--- ask for first date 
         if(SeriesInfoInteger(symbol,period,SERIES_FIRSTDATE,first_date)) 
            if(first_date>0 && first_date<=start_date) return(0); 
        } 
      //--- copying of next part forces data loading 
      int copied=CopyTime(symbol,period,bars,100,times); 
      if(copied>0) 
        { 
         //--- check for data 
         if(times[0]<=start_date)  return(0); 
         if(bars+copied>=max_bars) return(-2); 
         fail_cnt=0; 
        } 
      else 
        { 
         //--- no more than 100 failed attempts 
         fail_cnt++; 
         if(fail_cnt>=100) return(-5); 
         Sleep(10); 
        } 
     } 
     
     Print(" === 6 === ");
//--- stopped 
   return(-3); 
  } 
//+------------------------------------------------------------------+ 
//| Возвращает строкое значение периода                              | 
//+------------------------------------------------------------------+ 
string GetPeriodName(ENUM_TIMEFRAMES period) 
  { 
   if(period==PERIOD_CURRENT) period=Period(); 
//--- 
   switch(period) 
     { 
      case PERIOD_M1:  return("M1"); 
      case PERIOD_M2:  return("M2"); 
      case PERIOD_M3:  return("M3"); 
      case PERIOD_M4:  return("M4"); 
      case PERIOD_M5:  return("M5"); 
      case PERIOD_M6:  return("M6"); 
      case PERIOD_M10: return("M10"); 
      case PERIOD_M12: return("M12"); 
      case PERIOD_M15: return("M15"); 
      case PERIOD_M20: return("M20"); 
      case PERIOD_M30: return("M30"); 
      case PERIOD_H1:  return("H1"); 
      case PERIOD_H2:  return("H2"); 
      case PERIOD_H3:  return("H3"); 
      case PERIOD_H4:  return("H4"); 
      case PERIOD_H6:  return("H6"); 
      case PERIOD_H8:  return("H8"); 
      case PERIOD_H12: return("H12"); 
      case PERIOD_D1:  return("Daily"); 
      case PERIOD_W1:  return("Weekly"); 
      case PERIOD_MN1: return("Monthly"); 
     } 
//--- 
   return("unknown period"); 
  }

Результат работы:

2020.10.28 11:18:08.067 Test (FUTBRNJAN21,M1)   Start loadRTSCHH1,H1from2006.01.01 00:00:00
2020.10.28 11:18:08.067 Test (FUTBRNJAN21,M1)    === 1 === 
2020.10.28 11:18:08.067 Test (FUTBRNJAN21,M1)    === 2 === 1970.01.01 00:00:00
2020.10.28 11:22:01.741 Test (FUTBRNJAN21,M1)    === 2.1 === 18446744073475877138    Время выполнения SeriesInfoInteger(symbol,period,SERIES_FIRSTDATE,first_date); 
2020.10.28 11:22:01.741 Test (FUTBRNJAN21,M1)    === 2.2 === 
2020.10.28 11:22:01.741 Test (FUTBRNJAN21,M1)    === 2.3 === 
2020.10.28 11:22:01.741 Test (FUTBRNJAN21,M1)    === 3 === 

Конца выполнения скрипта я так и не дождался.

Пока в терминале есть такие баги, ни о каком боевом исполнении речи быть не может!!! 

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

SeriesInfoInteger(symbol,period,SERIES_FIRSTDATE,first_date)

Должна вернуть NULL моментально, почему время выполнения 18446744073475877138 ?


Может я чего не знаю?  Функции CopyXXX  так же зависают на 16-29 секунд!!! 

Это же не нормально, если у брокера 3000-6000 финасовых инструментов.

 
Vladimir Pastushak:

Может я чего не знаю?  Функции CopyXXX  так же зависают на 16-29 секунд!!! 

Это же не нормально, если у брокера 3000-6000 финасовых инструментов.

Бары - зло. Поэтому просьба в другой ветке постить про них.

 
fxsaber:

Бары - зло. Поэтому просьба в другой ветке постить про них.

Может быть Вы знаете как программно выбрать финансовый инструмент и не зависнуть на века ?

 
Vladimir Pastushak:

Может быть Вы знаете как программно выбрать финансовый инструмент и не зависнуть на века ?

Не сталкивался с такой задачей.

 
Aleksey Vyazmikin:

fxsaber , а если поставить низкий приоритет для агентов в диспетчере задач, а для MT5 высокий?

Не могу найти утилитку, которая бы блокировало выделение для всех программ/потоков ОС ресурса в виде конкретного потока ЦП, иначе можно было бы для MT5 резервировать поток и автоматически блокировать его занятие для других программ, что могло бы в теории снизить лаги.

Выставил для всех Агентов самый низкий приоритет.

Не помогает.


ЗЫ На результат влияет количество запущенных советников.

 

Уважаемые разработчики, могли бы Вы сообщить, как вычисляется MQL_MEMORY_USED?

Сделал расчет памяти, что занимают все переменные советника.

MQL_MEMORY_USED = 60 MB, Virtual = 3.40 MB ( 5.7%)

Это меньше 10%. Если правильно понимаю, то в MQL_MEMORY_USED входит History-кеш и CopyTicks-кеш. Но это все равно значительно меньше должно занимать.

При этом параллельный советник кушает в несколько раз меньше. Хотя принцип тот же.

В общем, что входит в это значение?


ЗЫ Сохранил шаблон с советником и к этому же чарту применил, вызвав перезагрузку. Стало так.

MQL_MEMORY_USED = 7 MB, Virtual = 3.40 MB ( 48.6%)

Потребление памяти изменилось почти на порядок. Сложно пока объяснить, что это обозначает.